在 Postgres 中跨表应用的非唯一约束名称

问题描述

通过 sqlAlchemy 和 Alembic,我创建了一些共享名称但在其他方面相互独立的表约束。这会产生一些令人惊讶的结果,其中约束检查应用于与约束规范不匹配的表中的列。

可重现的例子:

DROP TABLE IF EXISTS users;

CREATE TABLE users (
    id UUID DEFAULT uuid_generate_v4() NOT NULL,created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,join_date DATE,userrole VARCHAR(19) NOT NULL,status VARCHAR(24) NOT NULL,PRIMARY KEY (id),CONSTRAINT role CHECK (userrole IN ('standard','admin','readonly'))
);

DROP TABLE IF EXISTS groups;

CREATE TABLE groups (
    id UUID DEFAULT uuid_generate_v4() NOT NULL,grouprole VARCHAR(19) NOT NULL,CONSTRAINT role CHECK (grouprole IN ('foo','bar','baz'))
);

users 表中的检查将约束应用于 usersgroups 表中的列。同样,groups 表中的检查将约束应用于 groups users 表中的列。

检查在表之间交叉的地方,它应用于索引处的列,您希望它应用于定义它的表中。上面的例子结果如下:

用户

姓名 类型 可以为空 检查
1 id uuid 没有 NULL uuid_generate_v4()
2 created_at 时间戳 没有 (role)::text = ANY ((ARRAY['foo'::character 变化,'bar'::character 变化,'baz'::character 变化])::text[]) NULL
3 updated_at 时间戳 没有 NULL NULL
4 加入日期 日期 NULL NULL
5 用户角色 varchar(19) 没有 (role)::text = ANY ((ARRAY['standard'::character 可变,'admin'::character 可变,'readonly'::character 可变])::text[]) NULL
6 状态 varchar(24) 没有 NULL NULL

组:

姓名 类型 可以为空 检查
1 id uuid 没有 NULL uuid_generate_v4()
2 组角色 varchar(19) 没有 (role)::text = ANY ((ARRAY['foo'::character 变化,'bar'::character 变化,'baz'::character 变化])::text[]) NULL
3 created_at 时间戳 没有 NULL NULL
4 updated_at 时间戳 没有 NULL NULL
5 状态 varchar(24) 没有 (role)::text = ANY ((ARRAY['standard'::character 可变,'admin'::character 可变,'readonly'::character 可变])::text[]) NULL

更改约束之一的名称足以解决此问题。这是约束应该起作用的方式吗?

我创建了一个 DB Fiddle显示它适用于多个 Postgres 版本。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)