【问题标题】:New enum values must be committed before they can be used必须先提交新的枚举值,然后才能使用它们
【发布时间】:2021-03-15 17:50:16
【问题描述】:

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

BEGIN

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

END;

但在 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.

谷歌搜索表明这是早于 13,但我不知道具体是哪个版本。

我很确定我有充分的理由创建枚举、增加价值并在同一个交易中使用这个价值。问题末尾有详细信息。

是否有任何已知的干净解决方法?

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

我有一组 SQL 文件

v_0.01.sql
v_0.02.sql
v_0.03.sql
...

是增量的,即“数据库版本 X”包含在“直到 X 的所有 SQL 文件”中,例如版本 0.02 安装有

cat v_0.01.sql v_0.02.sql | psql -1

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

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

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

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

我想保留:

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

【问题讨论】:

  • 是的,请详细说明您的用例,因为这将使我们能够建议最明智的解决方法。
  • @Bergi 我刚刚做到了
  • 所以psql -1f v_0.01.sql && psql -1f v_0.02.sql 不适合您?
  • 这有一些缺点 - 例如。在某些阶段,使用单个文件更方便,例如db_upgrade_from_7.01_to_7.43 包含所有 43 个文件 - 但如果没有更好的方法,我肯定会考虑这个。

标签: postgresql enums


【解决方案1】:

已经是Postgres 9.6 docs on this 状态

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

当枚举是在同一个事务中创建时,这条规则似乎有一个未记录的例外。这根本不应该奏效。

自 Postgres 12 起,现在支持在事务期间添加新值,但不支持在同一事务中使用它们:

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

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

(Postgres 12.0 release notes)

看来这次对规则的修改修复了你使用的漏洞。

至于变通方法,您可能希望使用临时表来存储枚举并仅在事务结束时创建它们类型。查看Adding a new value to an existing ENUM Type(其中记录了ADD VALUE 之前的解决方案)以获得灵感。

【讨论】:

    猜你喜欢
    • 2018-02-20
    • 2019-10-24
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多