新的枚举值必须先提交才能使用

jbe*_*bet 8 postgresql enums

我正在将 PostgreSQL 从 9.6 升级到 13。以下脚本适用于 9.6:

BEGIN

CREATE TYPE x AS ENUM ('foo', 'bar');
ALTER TYPE x ADD VALUE 'baz';
SELECT 'baz'::x;

END;
Run Code Online (Sandbox Code Playgroud)

但 13 的结果是:

ERROR:  unsafe use of new value "baz" of enum type x
LINE 1: SELECT 'baz'::x;
               ^
HINT:  New enum values must be committed before they can be used.
Run Code Online (Sandbox Code Playgroud)

谷歌搜索表明它早于 13,但我不知道到底是哪个版本。

我很确定我有充分的理由创建枚举、添加值并在同一事务中使用该值。详情见问题末尾。

是否有任何已知的清洁解决方法?

[编辑] - 为什么我想这样做

我有一组 SQL 文件

v_0.01.sql
v_0.02.sql
v_0.03.sql
...
Run Code Online (Sandbox Code Playgroud)

是增量的,即“数据库版本 X”包含在“X 之前的所有 SQL 文件”中,例如版本 0.02 与

cat v_0.01.sql v_0.02.sql | psql -1
Run Code Online (Sandbox Code Playgroud)

其中一些文件包含CREATE TYPEs,其他一些文件包含ALTER TYPEs。我可能会在以后的文件中添加更多内容。

这很方便,因为在任何特定时刻我都可以轻松地:

  • 安装任何所需版本的新数据库
  • 将数据库从任何版本升级到任何其他版本
  • 检查版本之间的差异

在 9.6 上,第二个点需要更多的努力 - 即ALTER TYPE在事务之外执行任何操作。在 13 上,第一次操作也需要这样做,这很不方便,因为我更频繁地执行此操作,并且还有更多的总 SQL,因此有更多的ALTER TYPEs。

我想保留:

  • 当前文件结构
  • 轻松安装新数据库
  • 单事务安装 ( psql -1) - 这样我就不会混淆正确的安装和失败的安装

Ber*_*rgi 10

Postgres 9.6 文档已经介绍了这种状态

ALTER TYPE ... ADD VALUE(向枚举类型添加新值的形式)无法在事务块内执行。

当在同一事务中创建枚举时,此规则似乎存在未记录的例外情况。这根本不应该起作用。

从 Postgres 12 开始,现在支持在事务期间添加新值,但不支持在事务中添加新值:

  • 允许更灵活地添加枚举值(Andrew Dunstan、Tom Lane、Thomas Munro)

    以前,ALTER TYPE ... ADD VALUE无法在事务块中调用,除非它是创建枚举类型的同一事务的一部分。现在可以在稍后的事务中调用它,只要新的枚举值在提交之后才被引用。

Postgres 12.0 发行说明

看来规则的这一更改修复了您所使用的漏洞。

至于解决方法,您可能希望使用临时表来存储枚举并仅在事务的最后创建它们的类型。查看向现有 ENUM 类型添加新值(记录预ADD VALUE解决方案)以获得灵感。


Ora*_*ami 9

COMMIT;只需在行后添加即可ALTER TYPE提交数据库中的更改。

CREATE TYPE x AS ENUM ('foo', 'bar');
ALTER TYPE x ADD VALUE 'baz';
COMMIT;
SELECT 'baz'::x;
Run Code Online (Sandbox Code Playgroud)

如果您使用 Flyway 遇到此问题 - 将 alter 和 select 语句拆分到不同的文件中。