我正在构建一个必须在MySQL,PostgreSQL和SQLite上运行的数据库。我的一个表有一个两列主键:
CREATE TABLE tournament (
state CHAR(2) NOT NULL,
year INT NOT NULL,
etc...,
PRIMARY KEY(state, year)
);
我希望从另一个表中引用tournament
表,但我希望此引用为 nullable 。这就是我如何做到这一点,想象一个胜利者不一定有锦标赛:
CREATE TABLE winner (
name VARCHAR NOT NULL,
state CHAR(2) NULL,
year INT NULL
);
如果state
为空但year
不为,或反之亦然,则该表将不一致。我相信以下FOREIGN KEY
约束修复了它:
ALTER TABLE winner ADD CONSTRAINT FOREIGN KEY fk (name, state) REFERENCES tournament (name, state);
这是实施一致性的正确方法吗?这个架构是否正确规范化了?
答案 0 :(得分:4)
好的,我建议您查看ON DELETE
子句和MATCH
子句。因为,Pg非常符合SQL,我会指向CREATE TABLE
上的当前文档。
摘录:
这些子句指定外键 约束,这需要一个 一组一列或多列 新表必须只包含值 匹配引用的值 某些行的列 参考表。如果refcolumn是 省略,主键 使用reftable。引用 列必须是a的列 中的唯一或主键约束 引用的表。注意 外键约束不可能 在临时表和。之间定义 永久表格。
插入引用的值 列与...匹配 引用表的值和 使用给定的引用列 比赛类型。有三场比赛 类型:MATCH FULL,MATCH PARTIAL,和 MATCH SIMPLE,也是 默认。 MATCH FULL不允许一个 多列外键的列 除非所有外键列都为null 是空的。 MATCH SIMPLE允许一些 外键列为null时 外键的其他部分都没有 空值。 MATCH PARTIAL还没有 实现。
另外,当数据在 引用的列已更改,确定 对数据执行操作 这张表的专栏。 ON DELETE 子句指定要执行的操作 当一个被引用的行 引用的表正在删除。 同样,ON UPDATE子句 指定a时要执行的操作 引用的引用列 表正在更新为新值。 如果行更新了,但是 引用列实际上并不是 改变了,没有采取任何行动。 除NO之外的参考行动 即使是行动检查也不能推迟 如果声明了约束 缓征。有以下几点 每个条款可能采取的行动:
此外,MS SQL存在一个主要的例外 - 它不允许外键中的部分匹配(MATCH SIMPLE和MATCH PARTIAL)行为(默认值并强制执行MATCH FULL)。有一些解决方法,您可以在表的一部分上创建一个MATCH FULL索引,该索引对于任何复合键的组成部分都不是NULL。