我正在将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,但我不知 prop 体是哪个版本。
我确信我有一个很好的理由在同一个事务中创建枚举,添加值并使用这个值。
是否有任何已知的干净变通方案?
[编辑] -我为什么要这么做
我有一组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 TYPE
,另一些包含ALTER TYPE
。我可能会在以后的文件中添加更多这样的文件。
这很方便,因为在任何给定时刻,我都可以很容易地:
- 安装任何所需版本全新数据库
- 将数据库从任何版本升级到任何其它版本
- 检查版本之间的差异
在9.6上,第二个点需要更多的工作-即在事务之外执行任何ALTER TYPE
。在13上,第一个操作也需要这样做,这很不方便,因为我经常这样做,而且有更多的total-SQL,所以有更多的ALTER TYPE
。
我想保留:
- 现行文件结构
- 轻松安装全新数据库
- 单事务安装(
psql -1
)-这样我就不会把正确的安装与失败的安装混淆起来
3条答案
按热度按时间dwthyt8l1#
Postgres 9.6文档已在此状态
ALTER TYPE ... ADD VALUE
(向枚举类型添加新值的形式)不能在事务块内执行。在同一事务中创建枚举时,似乎存在未记录的此规则异常。这不应该起作用。
从Postgres 12开始,现在支持在事务期间添加新值,但不支持在相同的:
以前,不能在事务块中调用
ALTER TYPE ... ADD VALUE
,除非它是创建枚举类型的同一事务的一部分。现在,只要在提交新枚举值之前不引用它,就可以在以后的事务中调用它。(Postgres 12.0 release notes)
看来这条规则的修改弥补了你所利用的漏洞。
至于变通方法,您可能希望使用临时表来存储枚举,并仅在事务的最后创建它们的类型。看看Adding a new value to an existing ENUM Type(它记录了
ADD VALUE
之前的解决方案)以获得灵感。wooyq4lh2#
只需在
ALTER TYPE
行后添加COMMIT;
即可提交数据库中的更改。如果使用flyway时遇到这个问题-将alter和select语句拆分到不同的文件。
42fyovps3#
在
ALTER TYPE
对我起作用之后添加COMMIT;
。