演員陣容不是真的演員。這只是(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