Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 为什么可以使用这种外键?_Sql_Sql Server_Foreign Keys_Database Agnostic - Fatal编程技术网

Sql 为什么可以使用这种外键?

Sql 为什么可以使用这种外键?,sql,sql-server,foreign-keys,database-agnostic,Sql,Sql Server,Foreign Keys,Database Agnostic,为什么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 val

为什么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:这来自于此

注意2:这可以避免,在两列上都设置为NOTNULL

评论:我不是在问避免,我感兴趣的是哪些好处

参考资料:

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

  • :外键约束可以包含空值;但是,如果复合外键约束的任何列包含空值,则将跳过对构成外键约束的所有值的验证


我知道一些数据库管理系统在涉及外键约束的外键时根本不强制执行引用完整性。我想到了SQLite。大家都在谈论这件事

其他DBMS则不同,我知道如果您尝试这样的操作,MS SQL Server会抱怨


SQLite有它的用途,但它并不打算用于高并发情况。如果您在不同的DBMS中看到这种行为,请检查他们的文档,看看他们是否做了类似的事情。然而,大多数人应该强制执行完整性。

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


早期的SQL标准(SQL86)没有引用完整性,SQL89 level 2修复了这一点。

至少要用一个合理的标准RDBMS来完成开发工作,即使你用类似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.

尝试添加此声明:

alter table prova_b add主键(a,b)

这将禁止prova_b中的空值。它还将禁止重复条目。在Oracle和SQL server中,它还将创建索引。此索引将加快查找和连接,但代价是稍微降低插入速度

这就是你想做的吗


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

Oracle和SQL Server都允许空外键,很容易理解为什么需要空外键。 例如,设想一个树,其中每一行都有一个引用同一表的主键的父键。树中必须有一个没有父节点的根节点,并且父键将为null。 一个更具体的例子:想想员工和经理。公司中的一些人,如果只是CEO,就不会有经理。如果无法将employee表上的经理id设置为NULL,则必须创建一个“无经理”员工,这是错误的,因为它没有实际的通信


现在我们知道了这一点,很明显为什么复合关键点的行为与它们一样。从逻辑上讲,如果组合的一部分为NULL,则整个键为NULL。如果其中一个片段为NULL,字符串串联将返回NULL。不可能存在匹配,并且在这些情况下不强制执行约束。

我遇到了一个问题。SQLite的人必须这么说:外键约束被解析,但没有强制执行。但是,可以使用触发器实现等效的约束强制。colithium答案中的链接详细介绍了如何使用sqlite实现这一点。这并不是真正意义上的企业级DBMS,它也适用于Microsoft Sql Server。如果您不喜欢它,可以将prova_b中的列设置为NOT null,那么它就被破坏了,@beta。您应该不能在B中输入不在A中的值,否则ref int不起作用。Null和notnull在这里并不重要,重要的是外键。我认为,我们必须卸载所有标准关系数据库;-)我想当我说“当涉及外键时”,我没有说得很清楚。我的意思是存在外键约束。SQLite解析,但不强制执行约束。