代码之家  ›  专栏  ›  技术社区  ›  FerranB Tom

为什么这种外键是可能的?

  •  0
  • FerranB Tom  · 技术社区  · 16 年前

    为什么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 : 关系模型允许外键的值与引用的主键或唯一键的值匹配,或者为空。如果组合外键的任何列为空,则键的非空部分不必与父键的任何对应部分匹配。

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

    5 回复  |  直到 8 年前
        1
  •  4
  •   colithium    16 年前

    我知道有些dbms在涉及外键约束的外键时根本不强制引用完整性。想到了SQLite。有人说 here .

    其他的dbms是不同的,我知道MS SQL Server会抱怨如果你尝试类似的事情。

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

        2
  •  2
  •   Phil Factor    16 年前

    至少你的开发人员使用的是一个相当标准的关系数据库管理系统,即使你的生产系统使用的是类似SQLite(这是一个优秀的数据库,它运行在你的Ipod touch中!)它会冲掉所有这些错误-就像林特真的。如果您使用可以免费下载的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.
    
        3
  •  1
  •   cdonner    16 年前

    Oracle和SQL Server都允许空外键,很容易理解为什么这是必要的。 例如,想想树,其中每一行都有一个父键,该父键引用同一表的主键。树中必须有一个没有父节点的根节点,父键将为空。 一个更具体的例子:想想员工和经理。公司里有些人,如果只是首席执行官,就不会有经理。如果不能将employee表上的manager id设置为空,则必须创建一个“No manager”雇员,这是一个错误的做法,因为它没有实际的对应关系。

    现在我们知道了这一点,很明显,为什么组合键的行为与它们类似。逻辑上,如果组合的一部分为空,则整个键为空。如果其中一个片段为空,则字符串连接将返回空。不能有匹配项,并且在这些情况下不强制执行约束。

        4
  •  0
  •   paxdiablo    16 年前

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

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

        5
  •  0
  •   Walter Mitty    16 年前

    尝试添加此声明:

    alter table prova_b添加主键(a,b);

    这将禁止prova_b中的空值,也将禁止重复条目。在Oracle和SQL server中,它还将创建一个索引。这个索引将加快查找和连接的速度,但会降低插入的速度。

    这是你想做的吗?

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