演员阵容不是真的演员。这只是(ab)使用方便的语法。在后台创建一个large object (LO),后者将单独存储,并返回引用它的OID。
Per documentation:
所有大对象存储在名为 pg_largeobject
一个单一的系统表。每个大对象在系统 表pg_largeobject_metadata
中也有一个条目。大对象可以创建,修改, 并使用类似于文件上的标准 操作的读/写API删除。
返回的OID基本上是FK到系统表pg_largeobject
的PK。
CREATE TABLE
是完全独立于函数和伪演员。
CREATE TABLE bytea_to_lo (
largeObj lo
);
这只是一个典型的用例投上面创建的任务,然后从下面的行,你忘了引用变得很明显:
INSERT INTO bytea_to_lo VALUES (DECODE('00AB','hex'));
这里会发生什么?
数据类型lo
是在基底类型oid
,通过附加模块lo
(错误引用作为blog enty of Grace Batumbya“lo_manage包”)创建了一个域。 Per documentation:
该模块还提供了一种数据类型lo
,这是真正的oid
类型的只是一个域 。这对于区分容纳大对象引用的数据库列和其他事物的OID数据库列是很有用的。
功能decode()
返回bytea
。该INSERT
语句将bytea
值列largeObj
,这将触发一个赋值转换其类型lo
,而这也正是上面铸用武之地。
警告/纠正/更新
博客条目是草率和现在过时了。
不打扰一提的是(per documentation):
为了能够创造一个演员,你必须拥有源或目标 数据类型和对其他类型的USAGE
特权。
实际上,您必须是超级用户。
错字CREATE TABLE
:列名和类型颠倒过来。
函数定义是冗长而低效的。这将是更好的(Postgres的9.3或以上):
CREATE OR REPLACE FUNCTION blob_write(bytea)
RETURNS oid AS
$func$
DECLARE
loid oid := lo_create(0);
lfd int := lo_open(loid,131072); -- = 2^17 = x2000
-- symbolic constant defined in the header file libpq/libpq-fs.h
-- #define INV_WRITE 0x00020000
BEGIN
PERFORM lowrite(lfd, $1);
PERFORM lo_close(lfd);
RETURN loid;
END
$func$ LANGUAGE plpgsql VOLATILE STRICT;
SQL Fiddle.
有Postgres里9.4这一个built-in function。就用它来:
lo_from_bytea(loid oid, string bytea)
从release notes:
对于CREATE CAST
(per documentation):
第一个参数类型必须与演员的源类型相同或二进制强制。
我建议过载的变种,只有一个bytea
参数:
CREATE OR REPLACE FUNCTION lo_from_bytea(bytea)
RETURNS oid LANGUAGE sql AS
'SELECT lo_from_bytea(0, $1)';
CREATE CAST (bytea AS oid) WITH FUNCTION lo_from_bytea(bytea) AS ASSIGNMENT;
由于伪铸有相当大的副作用,我不相信做,一个ASSIGNMENT
演员。我可能会用显式才开始:
所以你 “发现” 了吗?你愿意链接到源代码吗? – 2015-04-03 14:51:22
@ErwinBrandstetter当然,我从[那里](https://gbatumbya.wordpress.com/2011/06/15/create-a-large-object-lo-from-binary-data-bytea-on-server -侧/)。 – user3663882 2015-04-03 15:07:43
相关:http://stackoverflow.com/questions/10139077/convert-a-bytea-column-to-oid-column-with-retained-values-postgresql – 2015-04-03 16:48:35