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

标签 postgresql plpgsql alter version-numbering

我在如何使用 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();

最佳答案

Postgres 8.2 引入了配置参数 server_version_numPer 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。
  • 返回配置参数 server_version,它也存在于 pg 8.1 中。
  • 我将 properties 替换为 the_column,假设这是另一个错误。
  • 不要使用大小写混合的名称。
  • 不要引用语言名称。使用 LANGUAGE plpgsql,无引号。

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

关于postgresql - 使用 plpgsql 将列 bytea 更改为各种版本的 Postgres 中的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28668969/

相关文章:

postgresql - PostgreSQL 中的小日期时间

postgresql - 恢复 .dump 文件 - "Permission Denied"

java - Postgres : Passing custom types from Java to postgres function

mysql - 在 MySQL 中创建虚拟表

sql - 我怎样才能让这条SQL更新语句更有效率呢?

performance - 使用 pg_stat_statements 收集大型统计集?

postgresql - 如何根据同一表中其他列的更改更新列值,而表中没有任何主键列

sql - PL/pgSQL : merge results from iterative function call in another function

php - 如何向 mysql 表添加唯一的记录号

mysql - ALTER TABLE ALL TABLES ROW_FORMAT=固定;