外键是指跨多个表的主键?

时间:2009-03-21 07:36:43

标签: sql foreign-keys primary-key

我必须在数据库员工下面有两个表,即employees_ce和employees_sn。

它们都有各自唯一的主键列。

我有另一个名为deductions的表,其外键列我想引用employees_ce的主键以及employees_sn。这可能吗?

例如

employees_ce
--------------
empid   name
khce1   prince

employees_sn
----------------
empid   name
khsn1   princess

这可能吗?

deductions
--------------
id      name
khce1   gold
khsn1   silver

7 个答案:

答案 0 :(得分:91)

假设我已正确理解您的场景,我就称之为正确的方式来执行此操作:

从数据库的更高级别描述开始!您有员工,员工可以是“ce”员工和“sn”员工(无论是那些员工)。在面向对象的术语中,有一个类“employee”,有两个子类叫做“ce employee”和“sn employee”。

然后,您将此更高级别的说明翻译为三个表格:employeesemployees_ceemployees_sn

  • employees(id, name)
  • employees_ce(id, ce-specific stuff)
  • employees_sn(id, sn-specific stuff)

由于所有员工都是员工(呃!),每个员工都会在employees表中排成一行。 “ce”员工在employees_ce表中也有一行,而“sn”员工在employees_sn表中也有一行。 employees_ce.id是[{1}}的外键,就像employees.id一样。

要引用任何类型的员工(ce或sn),请参阅employees_sn.id表。也就是说,您遇到问题的外键应该参考该表!

答案 1 :(得分:22)

你可以添加两个外键约束(老实说:我从来没有尝试过),但它坚持在两个表中都存在父行。

相反,您可能希望为两个员工子类型创建一个超类型,然后将外键指向那里。 (当然,假设你有充分的理由将这两类员工分开)。

                 employee       
employees_ce     ————————       employees_sn
————————————     type           ————————————
empid —————————> empid <——————— empid
name               /|\          name
                    |  
                    |  
      deductions    |  
      ——————————    |  
      empid ————————+  
      name
员工表中的

typecesn

答案 2 :(得分:18)

其实我自己这样做。我有一个名为'Comments'的表,其中包含3个其他表中记录的注释。这两种解决方案都没有真正处理您可能想要的一切。在你的情况下,你会这样做:

解决方案1:

  1. 在employees_ce和employees_sn中添加一个tinyint字段,其默认值在每个表中都不同(此字段表示'表标识符',因此我们将其称为tid_ce&amp; tid_sn)

  2. 使用表的PK和表ID字段在每个表上创建唯一索引。

  3. 在'Deductions'表中添加tinyint字段以存储外键的后半部分(表ID)

  4. 在“扣减”表格中创建2个外键(您无法强制执行参照完整性,因为其中一个键有效或另一个...但从不同时:

    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_ce] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_ce] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_ce]
    GO
    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_sn] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_sn] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_sn]
    GO
    
    employees_ce
    --------------
    empid    name     tid
    khce1   prince    1
    
    employees_sn
    ----------------
    empid    name     tid 
    khsn1   princess  2
    
    deductions
    ----------------------
    id      tid       name  
    khce1   1         gold
    khsn1   2         silver         
    ** id + tid creates a unique index **
    
  5. 解决方案2: 此解决方案允许维护参照完整性: 1.在“Deductions”表中创建第二个外键字段,允许两个外键中的Null值,并创建正常的外键:

        employees_ce
        --------------
        empid   name
        khce1   prince 
    
        employees_sn
        ----------------
        empid   name     
        khsn1   princess 
    
        deductions
        ----------------------
        idce    idsn      name  
        khce1   *NULL*    gold
        *NULL*  khsn1     silver         
    

    只有在列不为空时才会检查完整性,因此您可以保持参照完整性。

答案 3 :(得分:6)

我知道这是一个长期停滞的话题,但是如果有人在这里搜索我是如何处理多表外键的。使用此技术,您没有任何DBA强制级联操作,因此请确保在代码中处理DELETE等。

Table 1 Fruit
pk_fruitid, name
1, apple
2, pear

Table 2 Meat
Pk_meatid, name
1, beef
2, chicken

Table 3 Entity's
PK_entityid, anme
1, fruit
2, meat
3, desert

Table 4 Basket (Table using fk_s)
PK_basketid, fk_entityid, pseudo_entityrow
1, 2, 2 (Chicken - entity denotes meat table, pseudokey denotes row in indictaed table)
2, 1, 1 (Apple)
3, 1, 2 (pear)
4, 3, 1 (cheesecake)

SO Op的示例看起来像这样

deductions
--------------
type    id      name
1      khce1   gold
2      khsn1   silver

types
---------------------
1 employees_ce
2 employees_sn

答案 4 :(得分:1)

技术上可行。您可能会在扣减和employees_sn中引用employees_ce。但是你为什么不合并employees_sn和employees_ce?我没有理由说你有两张桌子。无人关系。而且(不是在这个例子中)很多列。

如果您对一列进行两次引用,则员工必须在两个表中都有一个条目。

答案 5 :(得分:1)

是的,有可能。您需要为第3个表定义2个FK。每个FK指向一个表的必需字段(即每个外表的1 FK)。

答案 6 :(得分:0)

假设由于某种原因您必须为两种员工类型设置两个表,我将继续讨论vmarquez的答案:

架构:

employees_ce (id, name)
employees_sn (id, name)
deductions (id, parentId, parentType, name)

扣除数据:

deductions table
id      parentId      parentType      name
1       1             ce              gold
2       1             sn              silver
3       2             sn              wood
...

这将允许您将演绎指向模式中的任何其他表。数据库级约束IIRC不支持这种关系,因此您必须确保您的应用程序正确管理约束(如果您有多个不同的应用程序/服务访问同一个数据库,这会使其更加麻烦)。 / p>