为什么SQL Standard会接受这个?有什么好处?
如果有这些表:
create table prova_a (a number, b number);
alter table prova_a add primary key (a,b);
create table prova_b (a number, b number);
alter table prova_b add foreign key (a,b) references prova_a(a,b) ;
insert into prova_a values (1,2);
您可以插入此内容而不会出现错误:
insert into prova_b values (123,null);
insert into prova_b values (null,123);
注1 :这来自answer。
Note2 :这可以避免,在两列上都设置为非空。
备注:我不是要求避免,我对哪些是受益者感兴趣。
参考文献:
Oracle documentation:关系模型允许外键的值匹配引用的主键或唯一键值,或者为null。如果复合外键的任何列为null,则键的非null部分不必匹配父键的任何相应部分。
SQL Server documentation: FOREIGN KEY约束可以包含空值;但是,如果复合FOREIGN KEY约束的任何列包含空值,则会跳过对构成FOREIGN KEY约束的所有值的验证。
答案 0 :(得分:4)
我知道有些DBMS在涉及具有外键约束的外键时根本不强制引用完整性。 SQLite浮现在脑海中。它被谈到here。
其他DBMS不同,我知道如果你尝试这样的话,MS SQL Server会抱怨。
SQLite有其用途,但它并不适用于高并发情况。如果您在不同的DBMS中看到此行为,请检查其文档以查看它们是否执行了类似的操作。但大多数人应该强制执行诚信。
答案 1 :(得分:2)
至少让你的DEV使用一个合理标准的RDBMS,即使你正在使用像SQLite这样的生产系统(这是一个优秀的数据库 - 它在你的Ipod触摸中运行!)它将清除所有这些错误 - 像林特真的。如果你使用SQL Server Express运行你的代码,你可以免费下载,你会收到很多错误,如...
Msg 8111, Level 16, State 1, Line 2
Cannot define PRIMARY KEY constraint on nullable column in table 'prova_a'.
Msg 1750, Level 16, State 0, Line 2
Could not create constraint. See previous errors.
答案 2 :(得分:1)
Oracle和SQL Server都允许NULL外键,很容易理解为什么这是必要的。 例如,可以考虑一棵树,其中每一行都有一个引用同一个表的主键的父键。树中必须有一个没有父节点的根节点,父节点为空。 一个更切实的例子:想想员工和经理。公司里的一些人,如果只是CEO,就不会有经理。如果不能将employee表上的manager ID设置为NULL,则必须创建一个“No Manager”员工 - 这是错误的,因为它没有真实的对应关系。
现在我们知道这一点,很明显为什么你的复合键表现得像他们一样。逻辑上,如果复合的一部分为NULL,则整个键为空。如果其中一个片段为NULL,则字符串连接返回NULL。不能匹配,在这些情况下不会强制执行约束。
答案 3 :(得分:0)
SQL标准不接受这个;您找到了一个不强制引用完整性的DBMS。如果您很聪明,请将其现在卸载。至少,不要将其用于生产目的。
早期的SQL标准(SQL86)没有引用完整性,SQL89级别2修复了它。
答案 4 :(得分:0)
尝试添加此声明:
alter table prova_b add primary key(a,b);
这将禁止NULLS进入prova_b。它还将禁止重复输入。在Oracle和SQL服务器中,它还将创建索引。该索引将加快查找和连接速度,但代价是减慢插入量。
这是你想要做的吗?
至于为什么标准SQL允许你做一些你认为愚蠢的事情,这是一个哲学问题。大多数工具允许一些愚蠢的选择。试图禁止所有愚蠢选择的工具通常最终会无意中禁止一些非常明智的选择。