Blob 是 MySQL 中的数据类型,可以帮助我们以二进制格式存储对象。出于安全原因或 MySQL 中的某些其他目的,它最常用于存储文件、图像等媒体文件。它可以存储和保存可变数量的数据,MySQL 中可以使用四种类型的 blob,即 LONGBLOB、MEDIUMBLOB、BLOB 和 TINYBLOB。所有这些类型的不同之处在于所需的存储空间和可以存储的最大长度。这些数据类型值通常被视为字节字符串或二进制字符串。

BLOB 值包含二进制字符集和排序规则。存储在此类列值中的字节具有数值,无论何时在 MySQL 中执行排序和比较都基于该数值。在本文中,我们将了解 BLOB 数据类型以及如何将表的列声明为 BLOB,我们将进一步讨论 BLOB 值在严格模式的不同设置下的行为,并查看与 BLOB 值相关的示例。



BLOB 数据类型

MySQL 中表的最大行大小为 65535,代表行的内部能力,即使存储引擎对行有更大的能力支持。该行的最大大小不包括其中的 BLOB 或 TEXT 数据类型列。除了用于行缓冲区,BLOB 值数据存储在内存的不同区域中,并且对于不同的存储引擎,对此类值的内存分配是不同的。每个存储引擎使用不同的方法来处理这种数据类型的数据。

所有 blob 数据类型的存储要求如下:

  • TINYBLOB – 长度+ 1 个字节,其中长度< 2^8
  • BLOB – 长度+ 2 个字节,其中长度< 2^16
  • MEDIUMBLOB – 长度+ 3 个字节,其中长度< 2^24
  • LONGBLOB – 长度+ 4 个字节,其中长度< 2^32

其中长度代表 blob 数据类型列包含的字符串的原始长度。

关于 BLOB 数据类型,您应该了解一些事情,如下所列 -

  • BLOB 数据类型是可变长度列,因此它被视为 VARBINARY 列。但是,它在某些方面与 VARBINARY 不同。每当 BLOB 列用于索引时,都需要提及将用于索引的前缀的长度,并且不能将默认值分配给 BLOB 列。
  • 每当 MySQL 中的严格模式被禁用并且我们尝试在 BLOB 列中插入超过列最大长度的值时,就会从插入的原始值中截断可以容纳该列的值,并且只插入截断的值随着警告的产生。
  • 如果在 Mysql 中启用了严格模式,则可以防止截断超过列最大长度的值,并引发错误,指出插入的值超出了定义的列长度。
  • 每当我们对 BLOB 列执行排序时,只考虑第一个 max_sort_length 字节进行排序。max_sort_length 变量的默认值为 1024。但是,我们可以进一步更改 max_sort_length 的值并增加它以在基于 BLOB 列对数据进行排序和分组时考虑该值的多个字节。
  • BLOB 的类型决定了列可以具有的最大大小,但是可以在客户端和服务器之间传输的值的实际最大可能大小取决于通信中使用的缓冲区大小和可用内存。可以通过简单地更改 max_allowed_packet 变量的值来更改缓冲区大小的最大容量。此变量的值需要在服务器以及客户端大小进行更改才能正常工作。

MySQL BLOB 示例

我们将创建一个名为 gallery 的表,其中包含 id、name 和 image 列。图像列将是 BLOB 数据类型。我们可以使用以下查询来创建我们的表 -

CREATE TABLE gallery (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR (255) NOT NULL,
image BLOB NOT NULL
);

输出:

BLOB使用场景 mysql mysql中blob_数据类型

在 PHP 中,我们可以使用 PDO 在具有 blob 数据类型列的表中插入值。我们将看到一个 PHP 程序,该程序将展示我们如何在数据库中插入和检索 blob 值,如下所示:

<?php

class galleryBlob {

    const DB_HOST = 'localhost';
    const DB_NAME = 'db';
    const DB_USER = 'root';
    const DB_PASSWORD = 'root';

    public function __construct() {
        $conStr = sprintf("mysql:host=%s;dbname=%s;charset=utf8", self::DB_HOST, self::DB_NAME);
        try {
            $this->pdo = new PDO($conStr, self::DB_USER, self::DB_PASSWORD);
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
    }

    public function insertImage($filePath, $name) {
        $blob = fopen($filePath, 'rb');
        $sql = "INSERT INTO gallery(name,image) VALUES(:name,:image)";
        $stmt = $this->pdo->prepare($sql);
        $stmt->bindParam(':name', $name);
        $stmt->bindParam(':image', $blob, PDO::PARAM_LOB);
        return $stmt->execute();
    }

    public function selectImage($id) {
        $sql = "SELECT name,image FROM gallery WHERE id = :id;";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(array(":id" => $id));
        $stmt->bindColumn(1, $name);
        $stmt->bindColumn(2, $image, PDO::PARAM_LOB);
        $stmt->fetch(PDO::FETCH_BOUND);
        return array("name" => $name,
            "image" => $image);
    }

    public function __destruct() {
        $this->pdo = null;
    }

}

$sampleImage = new galleryBlob();
$sampleImage->insertImage('sample.jpg', "image/jpg");
$a = $sampleImage->selectImage(1);
header("Content-Type:" . $a['name']);
echo $a['image'];
?>

上面代码保存文件名为 educba.php 并在浏览器上运行时的输出如下,因为这张图片是我插入的,名为 sample.jpg-

BLOB使用场景 mysql mysql中blob_数据类型_02

它显示了我们存储在 SQL 表库中的图像。让我们在 MySQL 中检索记录并检查画廊表的内容——

select id, name from gallery;

输出:

BLOB使用场景 mysql mysql中blob_php_03

当我们尝试使用以下查询语句检索 blob 值时,由于 jpg 文件存储在 blob 类型的图像列中,因此输出太大,这使得结果集庞大且在终端上不可读,因为 jpg 文件在终端上无法解析.

select * from gallery;

输出:

BLOB使用场景 mysql mysql中blob_php_04

结论

MySQL 中使用 blob 类型来存储媒体文件,如图像、pdf 文件、视频、报告等。使用此类型时要采取的预防措施如上所述。