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

时间:2012-04-13 10:21:47

标签: 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;

但这只是给我错误:

ERROR: cannot cast type bytea to oid

有没有办法达到我想要的目的?

5 个答案:

答案 0 :(得分:4)

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

要将bytea转换为大型对象,应使用大型对象的类文件API创建新的大对象:lo_create()获取新的OID,然后在写入模式下执行lo_open(),然后使用lo_write写入()或lowrite(),然后是lo_close()。

只有演员才能合理地做到这一点。

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

答案 1 :(得分:4)

我认为最好的答案可以在Grace Batumbya's Blog中找到

  

算法非常简单,获取二进制数据,如果为null,则返回null。否则创建一个大对象,并在lowrite函数中,传递二进制值,而不是文件的路径。

     

该程序的代码如下。请注意,应安装lo_manage包以使其正常工作。

create or replace function blob_write(lbytea bytea)
   returns oid
   volatile
   language plpgsql as
$f$
   declare
      loid oid;
      lfd integer;
      lsize integer;
begin
   if(lbytea is null) then
      return null;
   end if;

   loid := lo_create(0);
   lfd := lo_open(loid,131072);
   lsize := lowrite(lfd,lbytea);
   perform lo_close(lfd);
   return loid;
end;
$f$;
CREATE CAST (bytea AS oid) WITH FUNCTION blob_write(bytea) AS ASSIGNMENT;
  

现在,以下代码有效:       CREATE TABLE bytea_to_lo(          lo largeObj       );

INSERT INTO bytea_to_lo VALUES ( DECODE('00AB','hex'));

我尝试过它并且像魅力一样。

答案 2 :(得分:2)

Postgres 9.4 为此添加built-in function

lo_from_bytea(loid oid, string bytea)

来自release notes

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

对于旧版本,这比has been posted before更有效:

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;

STRICT修饰符比手动处理NULL更聪明。

SQL Fiddle.

更多相关答案:

答案 3 :(得分:0)

我确信它已经很晚了,但对于今后遇到同样问题的人来说。

我还遇到了一个类似的问题,我在文本列中的旧数据直接在列中而不是作为OID。当我试图在升级后的应用程序中使用该数据时,我也得到了

我利用这个线程的知识来解决这个问题。我强烈地感到无论谁遇到这个问题都肯定想看看这个here

答案 4 :(得分:-1)

为了解决这个问题,我成功地使用了Grace Batumbya的Blog:http://gbatumbya.wordpress.com/2011/06/中的blob_write程序。