在保留值的同时将bytea列转换为OID

Pet*_*ter 3 postgresql types casting oid bytea

我正在尝试将bytea列更改为具有类型oid并仍然保留值。

我尝试过使用类似的查询:

ALTER TABLE mytable ADD COLUMN mycol_tmp oid;
UPDATE mytable SET mycol_tmp = CAST(mycol as oid);
ALTER TABLE mytable DROP COLUMN mycol;
ALTER TABLE mytable RENAME mycol_tmp TO mycol;
Run Code Online (Sandbox Code Playgroud)

但这只是给我一个错误:

ERROR: cannot cast type bytea to oid
Run Code Online (Sandbox Code Playgroud)

有什么方法可以实现我想要的吗?

Dan*_*ité 5

Oid类型的列只是对实际存储在系统的pg_largeobject表中的二进制内容的引用。在存储方面,Oid为4字节整数。另一方面,bytea类型的列实际内容。

要将字节转换为大对象,应使用大对象的类似于文件的API创建一个新的大对象:lo_create()获取新的OID,然后在写入模式下使用lo_open(),然后使用lo_write()进行写入或lowrite(),然后lo_close()。

仅通过转换就不能合理地做到这一点。

基本上,您需要以您选择的语言(至少一个支持大对象API,包括plpgsql)编写约10行代码来进行此转换。


Erw*_*ter 5

Postgres 9.4为此添加了一个内置函数

lo_from_bytea(loid oid, string bytea)
Run Code Online (Sandbox Code Playgroud)

发行说明

  • 添加 SQL 函数以允许 [大对象读/写][12] 在任意偏移量 (Pavel Stehule)

对于旧版本,这比以前发布的更有效:

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;
Run Code Online (Sandbox Code Playgroud)

STRICT修改是比手动处理空聪明。

SQL小提琴。

更多在这个相关的答案: