Postgresql多个表具有相同的外键唯一约束
Posted
技术标签:
【中文标题】Postgresql多个表具有相同的外键唯一约束【英文标题】:Postgresql multiple tables with same foreign key unique constraint 【发布时间】:2015-03-19 17:04:33 【问题描述】:我在 PostgreSQL 9.4 上有以下表格
CREATE TABLE "user" (
id SERIAL PRIMARY KEY,
email CHARACTER VARYING NOT NULL,
password CHARACTER VARYING NOT NULL
);
CREATE TABLE "dealer" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES "user" (id) ON DELETE RESTRICT
);
CREATE TABLE "affiliate" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES "user" (id) ON DELETE RESTRICT
);
是否可以强制 user_id
值在表 dealer
和 affiliate
之间是唯一的?
【问题讨论】:
您是否在询问是否可以强制执行一个约束,允许 user_id 属于经销商或附属公司,但不能同时属于两者? @PeterHeadland 是的,从本质上讲,用户可以是经销商或附属公司,不能同时是两者。 看到您的(现已删除)评论并决定扩展我的答案。 【参考方案1】:有不同的设置用于 SQL 中的继承,为此您可以在表 user
中使用整数列 type
来标记用户的类型,并引用表 user_type (id,name)
1,dealer
和 2,affiliate
的值:
CREATE TABLE user_type (
id INTEGER PRIMARY KEY, --could be SERIAL
name text
);
INSERT INTO user_type VALUES (1,'dealer'), (2, 'affiliate');
CREATE TABLE "user" (
id SERIAL PRIMARY KEY,
email CHARACTER VARYING NOT NULL,
password CHARACTER VARYING NOT NULL,
user_type INTEGER REFERENCES user_type NOT NULL,
UNIQUE(id,user_type)
);
这本身不会强制跨表的唯一性,因此在实施后您将拥有以下选项:
删除表dealer
和 affiliate
- 如果您依靠类型字段来查看用户是谁,则不需要它们。
如果您必须保留那些继承的表,您可以:
使用触发器 - 这些触发器检查唯一性并将在INSERT
或UPDATE
上激活
另一个(有点笨拙)的解决方案:将user_type
字段添加到两个子表,如下所示:
CREATE TABLE "dealer" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
user_type INTEGER NOT NULL DEFAULT 1 check (user_type = 1),
FOREIGN KEY (user_id,user_type) REFERENCES "user"(id,user_type) ON DELETE RESTRICT
);
CREATE TABLE "affiliate" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
user_type INTEGER NOT NULL DEFAULT 2 check (user_type = 2),
FOREIGN KEY (user_id,user_type) REFERENCES "user"(id,user_type) ON DELETE RESTRICT
);
检查和外键一起确保您不能在主表中同时拥有这两种类型的用户。请注意,user_id
也可以用作子表中的PRIMARY KEY
。目前user
中的一行可能有多个链接到它的dealer
行,因此至少您可能希望将子表中的user_id
外键设置为UNIQUE
。
【讨论】:
以上是关于Postgresql多个表具有相同的外键唯一约束的主要内容,如果未能解决你的问题,请参考以下文章
外键为啥必须是唯一键?为啥至少唯一键才能作为其他表的外键?不唯一为啥不可以?