【问题标题】:Adding and Renaming a field to ENUM Type in Postgres and preserving multiple ENUM types to be used in a field在 Postgres 中将字段添加和重命名为 ENUM 类型并保留要在字段中使用的多个 ENUM 类型
【发布时间】:2020-10-27 06:33:16
【问题描述】:

我正在使用 Postgres 和 postgres-migrations 来处理数据库迁移。

在第一个迁移脚本中,已定义基于以下 ENUM 标签的 TYPE。一个用户可以有多个角色。

CREATE TYPE user_role AS ENUM('PRIMARY', 'BILLING', 'CONTENT');

到目前为止,此类型已在 DB 中的两个表中使用,位于分配的 user_roles[] 数组中 - 列角色(这里是一个示例):

CREATE TABLE memberships (
id uuid DEFAULT uuid_generate_v1() PRIMARY KEY,
organisation_id uuid NOT NULL REFERENCES 
organisations(id),
roles user_role[] NOT NULL,
user_id uuid NOT NULL REFERENCES users(id)
);

我的目标是添加一个“ADMIN”用户角色,同时还希望在以后的迁移脚本中将“CONTENT”重命名为“EDITOR”。

我最初尝试过,

ALTER TYPE user_role ADD VALUE 'ADMIN';

ALTER TYPE user_role RENAME VALUE 'CONTENT' TO 'EDITOR';

但是我遇到了以下错误:

ALTER TYPE ... ADD 不能在 runMigrations 的事务块内运行

经过多次尝试在网上找到的解决方案后,我得出了这个结论:

ALTER TYPE user_role RENAME TO user_role_old;

CREATE TYPE user_role AS ENUM('PRIMARY', 
'ADMIN', 'EDITOR', 'BILLING');

ALTER TABLE memberships ALTER COLUMN roles TYPE 
user_role USING roles::text::user_role;

ALTER TABLE organisation_invites ALTER COLUMN 
roles TYPE user_role USING 
roles::text::user_role;

DROP TYPE user_role_old;

这现在在user_role 类型中给出了正确的标签,但是这用user_roles 替换了user_roles[] 的角色列类型。因此,我现在只能为一个不好的用户分配一个角色。我相信这与铸造和使用 text 有关,但我不确定。

【问题讨论】:

    标签: database postgresql enums


    【解决方案1】:

    您应该始终使用数组。我很惊讶这些语句不会导致错误(所有行的列都是 NULL 吗?)。

    ALTER TABLE memberships
       ALTER COLUMN role TYPE user_role
       USING roles::text[]::user_role[];
    

    如您所见,一旦值发生变化,您就会在使用枚举类型时遇到麻烦。

    如果值有可能改变或消失,我的建议是使用查找表。

    【讨论】:

    • 感谢您的回复 Laurenz,实际上我今天下午已经尝试过您的推荐,但没有成功。我收到以下错误 result of USING clause for column "roles" cannot be cast automatically to type user_role 这是我提到的铸造问题的一个例子
    • Laurenz,你运行的是哪个版本的 Postgres?
    • 版本 11.2,但我认为最近没有改变。
    【解决方案2】:

    我在使用Laurenz Albe's suggestion 后遇到了同样的问题,产生了以下错误:

    “角色”列的 USING 子句的结果无法自动转换为 user_role 类型

    解决这个问题的方法是将ALTER COLUMN 中的TYPE user_role(枚举)更新为user_role[](枚举数组):

    ALTER TABLE memberships
       ALTER COLUMN roles TYPE user_role[]
       USING roles::text[]::user_role[];
    

    【讨论】:

      【解决方案3】:

      所以在检查了我们运行的是哪个版本的 Postgres 之后,我发现我们正在使用

      PostgreSQL 9.6.11 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4, 64-bit
      

      这解释了为什么会这样

      -- postgres-migrations disable-transaction
      ALTER TYPE user_role ADD VALUE 'ADMIN';
      

      但不是,

      ALTER TYPE user_role RENAME VALUE CONTENT TO EDITOR
      

      RENAME VALUE 仅支持 PG 10 或更高版本。

      查看 Compose,他们似乎还不支持 PG 10。

      将数据库提供程序更改为运行 V.10 的 AWS,并且可以正常工作。

      仍然不确定为什么我无法让 Laurenz 的解决方案发挥作用,因为它似乎也是正确的。

      【讨论】:

        猜你喜欢
        • 2019-01-21
        • 2013-09-15
        • 2012-03-21
        • 2020-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多