MySQL中的二进制数据

199

我怎样将二进制数据存储在 MySQL 中?


2
@Nevir:你具体需要什么信息?你认为@phpguy@Mat的回答缺少什么? - eggyal
由于我无法发布答案,我猜我会在这里回答。如果您想存储某些二进制数据,可以创建一个表,设置一个PHP文件或脚本来存储它,并将某些二进制数据写入您的表,并让脚本完成它的工作。说真的,我实际上不知道如何在其他语言中使用PHP... - user14273431
9个回答

143

phpguy的答案是正确的,但我认为在附加细节中存在很多混淆。

基本答案在于数据类型/属性域。 BLOB是Binary Large Object的缩写,该列数据类型专门用于处理二进制数据。

请参阅MySQL相关手册页面.


59

对于这样的表格:

CREATE TABLE binary_data (
    id INT(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    description CHAR(50),
    bin_data LONGBLOB,
    filename CHAR(50),
    filesize CHAR(50),
    filetype CHAR(50)
);

以下是一个PHP示例:

<?php
    // store.php3 - by Florian Dittmer <dittmer@gmx.net>
    // Example php script to demonstrate the storing of binary files into
    // an sql database. More information can be found at http://www.phpbuilder.com/
?>

<html>
    <head><title>Store binary data into SQL Database</title></head>

    <body>
        <?php
            // Code that will be executed if the form has been submitted:

            if ($submit) {
                // Connect to the database (you may have to adjust
                // the hostname, username or password).

                mysql_connect("localhost", "root", "password");
                mysql_select_db("binary_data");

                $data = mysql_real_escape_string(fread(fopen($form_data, "r"), filesize($form_data)));

                $result = mysql_query("INSERT INTO binary_data (description, bin_data, filename, filesize, filetype) ".
                                    "VALUES ('$form_description', '$data', '$form_data_name', '$form_data_size', '$form_data_type')");

                $id= mysql_insert_id();
                print "<p>This file has the following Database ID: <b>$id</b>";

                mysql_close();
            } else {

                // else show the form to submit new data:
        ?>
        <form method="post" action="<?php echo $PHP_SELF; ?>" enctype="multipart/form-data">
            File Description:<br>
            <input type="text" name="form_description"  size="40">
            <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
            <br>File to upload/store in database:<br>
            <input type="file" name="form_data"  size="40">
            <p><input type="submit" name="submit" value="submit">
        </form>

        <?php
            }
        ?>
    </body>
</html>

9
这段代码看起来像是启用了register_globals的PHP3(或者可能是4)版本。你不想运行这段代码,并且它也无法在半新的PHP安装上(即5版本)正常工作。 - Till
28
请停止使用addslashes()函数来代替mysql_real_escape_string()函数,因为前者无法有效防止SQL注入攻击。我们应该避免给人们带有SQL注入漏洞的代码。(是的,addslashes()函数并不足够安全。) - chaos

43
我强烈建议不要在关系型数据库中存储二进制数据。关系型数据库是设计用来处理固定大小数据的;这也是它们性能优势所在:还记得Joel's old article关于为什么数据库如此快吗?因为只需要1个指针增量就可以从一个记录移动到另一个记录。如果添加大小不确定且差异巨大的BLOB数据,将会影响性能。
相反,将文件存储在文件系统中,并在数据库中存储文件名。

11
我没有点踩,但可能是因为他暗示你永远不应该这样做,而不是说大多数情况下这是个坏主意。一般来说,我同意他的观点,但并非在所有情况下都如此。除了性能之外还有其他考虑因素。例如,我现在正在处理一些与性能无关的东西。在这种情况下,像集中化、简单性和备份等其他因素意味着将其存储在数据库中是有意义的。另一个常见的原因是复制。 - LaVache
4
另一方面,在数据库中存储数据与操作系统无关,这对于奇怪的文件名可能是有好处的。数据库可以存储多个同名文件,而操作系统则不行。它没有读/写/删除问题,也不需要额外的备份系统。此外,它不是公开的。因此,有时在开发过程中速度很快。顺便说一句,没有人强迫您将所有内容都存储在同一个数据库中,最终所有东西都会落到磁盘上。 - Joeri
7
@AlexWeinstein,你把二进制数据和定长数据混淆了。二进制数据也可以是定长的。而且定长数据并不适用于所有情况。实际上,在许多情况下,你会从可变宽度数据中受益:请阅读http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html的最后一段。 - Pacerier
4
同意 @Pacerier 的观点,BINARY(16) 是固定存储的。至于 BLOB:BLOB 有一个指向存储在表外的数据的固定宽度指针。这与 varchar 或 varbinary 存储在内部不同。搜索 BLOB 需要一些额外的步骤,但是如果将其从 WHERE 子句中省略,则没问题。 - Garr Godfrey
4
我认为将文件存储在文件系统中非常易损坏且不可移植。如果文件被删除了怎么办? - Garr Godfrey
显示剩余3条评论

23

18

这取决于您希望存储的数据。上面的示例使用LONGBLOB数据类型,但您应该知道还有其他二进制数据类型:

TINYBLOB / BLOB / MEDIUMBLOB / LONGBLOB
VARBINARY
BINARY

每种数据类型都有其使用场景。如果它是已知(短)长度的数据(例如打包数据),则BINARYVARBINARY大部分情况下都能正常工作。它们还有一个附加好处,就是可以对它们进行索引。


15

虽然这不是必要的,但你可以尝试使用base64编码数据,并将其解码。这意味着数据库仅包含ASCII字符。虽然需要更多的空间和时间,但任何与二进制数据有关的问题都将被消除。


12
如果存在 - 不推荐使用 - BLOB 字段,您可以通过以下方式保存数据:
mysql_query("UPDATE table SET field=X'".bin2hex($bin_data)."' WHERE id=$id");

灵感来源于这里


12

11

问题也出现在如何将数据存入BLOB中。您可以像PHP示例所示一样将数据放入INSERT语句中(尽管您应该使用mysql_real_escape_string而不是addslashes)。如果文件存在于数据库服务器上,则还可以使用MySQL的LOAD_FILE函数。


那个链接说,MySQL_real_escape_string 已经被弃用了。 - Poul Bak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接