2009-02-06 90 views
0

为什么SQL标准接受这个?哪些好处?为什么这种外键可能?

如果有这些表:

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

注2:这可以避免,两列设置不为空。

备注:我不是在问关于避免,我关心哪些是好处。

参考文献:

  • Oracle documentation关系模型允许外键的值要匹配被引用的主键或唯一键的值,或为null。如果组合外键的任何列为空,则该键的非空部分不必匹配父键的任何对应部分。

  • SQL Server documentationFOREIGN KEY约束可以包含空值;但是,如果复合FOREIGN KEY约束的任何列包含空值,则会跳过组成FOREIGN KEY约束的所有值的验证。

回答

4

我知道某些DBMS只是当它涉及到与外键约束外键并不强制参照完整性。 SQLite浮现在脑海。这是谈到here

其他数据库管理系统是不同的,我知道如果你尝试类似的东西,MS SQL服务器会投诉。

SQLite有其用途,但它并不意味着在高并发情况下使用。如果您在不同的DBMS中看到此行为,请检查他们的文档以查看他们是否做了类似的事情。但大多数应该是强制执行完整性。

+0

MSSQL允许这... – FerranB 2009-02-06 09:04:18

+0

我想我并不明确,当我说,“当涉及到外键”。我的意思是存在外键约束。 SQLite解析,但不强制约束。 – colithium 2009-02-06 11:17:15

0

SQL标准不接受这个;你已经找到了一个不强制引用完整性的DBMS。卸载它现在如果你很聪明。至少,不要将其用于生产目的。

早期的SQL标准(SQL86)没有参照完整性,SQL89级别2修复了这个问题。

2

至少可以使用合理标准的RDBMS来开展您的DEV工作,即使您正在使用SQLite(这是一个优秀的数据库 - 它运行在您的Ipod touch中)来执行您的生产系统!它将清除所有这些错误 - 像Lint真的。如果你使用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. 
0

尝试增加此声明:

ALTER TABLE prova_b添加主键(A,B);

这将禁止NULLS在prova_b中。它也会禁止重复输入。在Oracle和SQL服务器中,它也会创建一个索引。这个索引将加速查找和连接,代价是减慢插入一点点。

这是你想要做的吗?

至于为什么标准SQL让你做一些你认为很愚蠢的事情,那是一个哲学问题。大多数工具允许一些愚蠢的选择。试图禁止所有愚蠢选择的工具通常最终会无意中禁止一些真正聪明的选择。

1

Oracle和SQL Server都允许NULL外键,并且很容易理解为什么这是必需的。 想象一棵树,例如,每一行都有一个引用同一个表的主键的父键。树中必须有一个没有父节点的根节点,并且父键将为空。 一个更具体的例子:想想员工和经理。公司中的一些人,如果只是首席执行官,则不会有经理。如果不能将员工表上的经理ID设置为NULL,则必须创建一个“无经理”员工 - 这是错误的,因为它没有真实的对应关系。

现在我们知道了这一点,这很明显,为什么你的复合键的行为就像他们一样。逻辑上,如果组合的一部分为NULL,则整个密钥为空。如果其中一个块为NULL,则字符串连接会返回NULL。无法匹配,并且在这些情况下不会强制约束。