5

我正在尝试将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

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

4

5 回答 5

6

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

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

仅靠演员阵容无法合理地做到这一点。

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

于 2012-04-13T10:51:49.220 回答
5

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

lo_from_bytea(loid oid, string bytea)

发行说明

  • 添加 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;

STRICT修饰符比手动处理 NULL 更智能。

SQL小提琴。

更多相关答案:

于 2015-04-03T17:05:19.000 回答
4

我认为最好的答案可以在Grace Batumbya 的博客中找到,原文

算法很简单,获取二进制数据,如果为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'));

我已经尝试过了,它就像一个魅力。

于 2013-05-03T21:38:12.687 回答
0

我相信它已经晚了,但是对于将来遇到同样问题的任何人。

我也遇到了类似的问题,我在文本列中有旧数据,而不是 OID。当我尝试将这些数据与升级的应用程序一起使用时,我也得到了

我用这个线程的知识来解决这个问题。我强烈觉得任何偶然发现这个问题的人肯定想看看这里

于 2015-04-07T05:25:45.130 回答
-1

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

于 2012-08-28T08:58:53.710 回答