使用 plpgsql 将列 bytea 更改为各种版本的 Postgres 中的文本

Alter column bytea to text in various versions of Postgres with plpgsql

我在如何使用 plpgsql 转换列时遇到问题 (bytea -> text)。我编写的函数适用于某些数据库,但不适用于其他数据库。我不知道如何解决它。
使用 8.0 - 9.3 的数据库;此错误适用于 8.1.19。

我收到了:

ERROR:  column "the_column" cannot be cast to type "text"
CONTEXT:  SQL statement "ALTER TABLE the_table ALTER COLUMN the_column TYPE text"
PL/pgSQL function "byteatotext" line 11 at execute statement

我的函数:

CREATE OR REPLACE FUNCTION byteaToText()
  RETURNS text AS
  $BODY$
    DECLARE
      ver int;
    BEGIN
      SELECT into ver (select setting from pg_settings where name='server_version_num') as test;
      IF ver < 80200 THEN
        EXECUTE 'ALTER TABLE the_table ALTER COLUMN the_column TYPE text USING ENCODE(properties, \'escape\'))';
        RETURN ver;
      ELSE
        EXECUTE 'ALTER TABLE the_table ALTER COLUMN the_column TYPE text';
        RETURN ver;
      END IF;
    RETURN 'error';
    END;
  $BODY$
  LANGUAGE 'plpgsql' VOLATILE;

select byteaToText();

配置参数 server_version_num 是随 Postgres 8.2 引入的。 Per documentation:

Add new configuration parameter server_version_num (Greg Sabino Mullane)

This is like server_version, but is an integer, e.g. 80200. This allows applications to make version checks more easily.

您的代码在 pg 8.1 中找不到不存在的参数并且没有分配给 ver,因此它保持为 NULL 并且控制最终在 ELSE 分支中 - 这也被指示在错误消息中:

ERROR:  column "the_column" cannot be cast to type "text"
CONTEXT:  SQL statement "ALTER TABLE the_table ALTER COLUMN the_column TYPE text"
PL/pgSQL function "byteatotext" line 11 at execute statement

将函数重写为:

CREATE OR REPLACE FUNCTION bytea_to_text()
  RETURNS text AS
$func$
BEGIN
   -- the config param was introduced with version 8.2
   PERFORM 1 FROM pg_settings WHERE name = 'server_version_num';

   IF FOUND THEN  -- version >= 8.2
      EXECUTE 'ALTER TABLE the_table ALTER COLUMN the_column TYPE text';
   ELSE
      EXECUTE 'ALTER TABLE the_table ALTER COLUMN the_column TYPE text USING encode(the_column, ''escape''))';
   END IF;

   RETURN (SELECT setting FROM pg_settings WHERE name = 'server_version');
END
$func$ LANGUAGE plpgsql;

备注

  • 未经 Postgres 8.1 测试,没有人再使用那么旧的 Postgres。
  • Return 配置参数 server_version 相反,它也存在于 pg 8.1 中。
  • 我将 properties 替换为 the_column,假设这是另一个错误。
  • 不要使用大小写混合的名称。
  • 不要引用语言名称。使用 LANGUAGE plpgsql,没有引号。

旁白:
显而易见的解决方案是将您的 Postgres 服务器升级到 运行 电力版本,而不是蒸汽版本。 Postgres 8.1 是 10 年前编写的,已于 2010 年 11 月停产。除此之外,至少更新到最后一个版本,即 8.1.23。