BLOB是大二进制数据的缩写。它是指任何需要存入数据库的随机大块比特,例如图片或声音文件。这里的要点是BLOB是一个在数据库内部不能被翻译的对象。
整件事开始于我需要将一些图形作为一个PHP Web应用程序的一部分存入一个PostgreSQL数据库。尽管PostgreSQL以Inversion Large Object(反转大对象)的形式提供了对BLOB的支持,但是你不能使用一般的SQL命令操控它们。PostgreSQL的大对象有自己的API,这在PHP里通过函数pg_locreate,pg_loopen,pg_lowrite,pg_loread,pg_loreadall,pg_loclose和pg_lounlink实现的。(见表A)
表A
函数 |
描述 |
pg_locreate |
创建一个大对象并返回它的oid(对象身份)——一个用于区别PostgreSQL数据库实体的数字。 |
pg_loopen |
在给定oid时,打开一个大对象,然后返回一个能在今后对它进行操控的filedescriptor。 |
pg_lowrite |
在给定文件描述符时,向一个打开的大数据库写入任意字节的数据。 |
pg_loread |
在给定文件描述符时,从一个打开的大数据库读出任意字节的数据。 |
pg_loreadall |
在给定文件描述符时,读出整个大的对象。 |
pg_loclose |
选择先前打开的大对象。 |
pg_lounlink |
在给出oid时,删除数据库里的大对象。 |
PostgreSQL大对象API
为了处理大对象,PostgreSQL提供了一个类似于文件I/O的独立API,前者在PHP里的是函数(详细情况见PHP/PostgreSQL文档)。
你必须存储由pg_locreate返回的对象身份标识(oid),通常是作为相关表的一列,以便于能够在今后访问这个大对象。PostgreSQL为此提供了一个数据类型(oid)。但是如果由于某些原因你丢失了大对象的oid,除了检查整个系统的表以找到它的oid就没有别的办法检索或者删除这个对象。这将是个很大的问题。
只要有一个清晰、没有错误的应用程序,这种情况通常是不会发生的。但是总会存在由于外部原因导致应用程序出错的危险,这会导致大对象的遗失。所以为了保险起见,一个规则的、清晰的程序是必需的。
另外一个关于PostgreSQL的解决方案问题是没有可以操控大对象的SQL命令,所以你必须编写脚本以执行甚至是最小的任务。这倒不是很麻烦,因为你的应用程序应该提供了所需的操作,但是我还是希望能够使用psql(PostgreSQL前端)来手动操控表和行。
将大对象作为表里的行来存储同时解决了这两个问题,因为事务处理保证了数据库的完整(没有查寻不到的大对象),而且表也可以通过SQL操控。但是SQL92标准没有为此定义任何合适的数据类型。
在SQL92标准定义的数据类型中,最好的选择是字符类型,它能存储变长串。但是,字符类型是为了存储字符而非二进制数据而设计的。尽管SQL92标准没有明确指出数据类型容量的限制,但是每个实际的产品都作出了上限。