【问题标题】:does foreign key always reference to a unique key in another table?外键是否总是引用另一个表中的唯一键?
【发布时间】:2012-02-01 03:03:00
【问题描述】:

子表中的外键(单列)是否不可能引用具有一些重复值的父键?

【问题讨论】:

    标签: oracle key parent


    【解决方案1】:

    根据 SQL 标准,外键必须引用父表的主键或唯一键。如果主键有多个列,则外键必须具有相同的列数和顺序。因此外键引用父表中的唯一行;不能有重复。


    你的评论:

    如果T.A 是主键,那么不,您不能有任何重复项。任何主键都必须是唯一且非空的。因此,如果子表有一个引用父表主键的外键,它必须匹配一个非空的唯一值,因此只引用父表中的一行。在这种情况下,您不能创建引用多个父行的子行。

    可以创建一个外键列为 NULL 的子行,在这种情况下,它不会引用父表中的任何行。

    【讨论】:

    • 谢谢,但是如果我们谈论单列外键,例如列 'a' 是子表 t 中的外键,它引用父表 T 中的列 'A',那么现在不是在任何情况下,A 列可能在表 T 中有任何重复值?这是否意味着外键迷雾是指另一个表中的主键??
    • @ratsy:外键必须始终引用声明为 PRIMARY KEY 或 UNIQUE 的一个或多个列。 (除非您使用的是 MySQL。但即使在 MySQL 中,您仍应仅定位 PRIMARY KEY 或 UNIQUE 列。搜索 dev.mysql.com/doc/refman/5.6/en/… 以获取“系统不强制要求引用的列必须是唯一的”。)
    • @Catcall:是的,但是@ratsy 标记了这个问题oracle,所以我没有提出 InnoDB 的非标准行为。即使在使用 InnoDB 时,我也强烈建议不要引用非唯一的父行,因为这样很容易混淆。
    • 非常感谢 Bill,Catcall 的澄清……我也问过这个问题,因为在我的组织中,我们正在整理总和数据库,并且在其中一个我发现外键引用了一个父键,它有两个三个重复记录在它的表(父表)中,父键在这里没有定义为主键:(..所以是的,Catcall 理解了我的问题,这里正在谈论 abt 的数据库仍然是一个 oracle 数据库。再次感谢比尔,所以这应该如何纠正..
    【解决方案2】:

    不,这是不可能的。

    当你在一张表上定义外键约束时,这意味着在外表上只有一个对应的键。如果外表上存在多个倍数,那意味着哪一个?

    维基百科在Foreign key 条目上有这个定义:

    外键是关系表中与另一个表的候选键匹配的字段

    候选键在表中是唯一的。

    【讨论】:

      【解决方案3】:

      是的,外键可以引用具有重复值的列。

      如果主键使用非唯一索引并且在创建时未经过验证,则可能会发生这种情况。 (但我在现实生活中从未见过这样的情况。正如@Bill Karwin 指出的那样,这会非常令人困惑。所以这可能不是你真正需要担心的情​​况。)

      --Create a table with two duplicate rows
      create table test1(a number);
      insert into test1 values(1);
      insert into test1 values(1);
      commit;
      
      --Create a non-unique index
      create index test1_index on test1(a);
      
      --Use the non-unique index for the primary key, do not validate
      alter table test1 add constraint test1_pk primary key (a)
          using index test1_index novalidate;
      
      --Build another table with a foreign key to TABLE1
      create table test2(a number,
          constraint test2_fk foreign key (a) references test1(a));
      
      --Inserting a value that refers to the duplicate value still works.
      insert into test2 values(1);
      commit;
      
      --The foreign key still works:
      --ORA-02291: integrity constraint (TEST2_FK) violated - parent key not found
      insert into test2 values(2);
      
      --The primary key works as expected, but only for new values:
      --ORA-00001: unique constraint (TEST1_PK) violated
      insert into test1 values(1);
      

      【讨论】:

      • 古怪。我认为这属于“你为什么要这样做?”的范畴。 :-) 但是感谢您提供的清晰示例!
      • 感谢 Jonearles 提供上述示例!........在使用的数据库中的情况相同,但为什么以及如何......?
      • 对主键使用非唯一索引有几个很好的理由;可延迟的约束、更多的重建选项(特别是并行性)、约束之前存在的索引等。在此处查找有关唯一与非唯一索引的信息:richardfoote.wordpress.com/2008/06/04/… NOVALIDATE 有点奇怪。据我所知,使用它没有任何好处,除非您只需要一些“坏”数据。这些案例确实应该记录在案。如果没有记录,也许这只是一个错误?
      • 哦,好吧..非常感谢 Jonearles 为我澄清了这一点......我正在谈论的 db 没有关于这些重复记录的文档,但是错误的 db 那么......如果愿意的话,可以回到这里需要有关此的任何帮助..但是感谢您解释得很好....
      猜你喜欢
      • 2018-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-20
      • 2011-04-17
      • 2021-08-17
      • 2016-08-18
      相关资源
      最近更新 更多