96

我有两个表,即employees_ce 和employees_sn 数据库employees 下。

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

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

例如

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

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

那么这可能吗?

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

7 回答 7

107

假设我已经正确理解了您的情况,这就是我所说的正确方法:

从您的数据库的更高级别描述开始!您有员工,员工可以是“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_snemployees_ce.id是 的外键employees.id,就像employees_sn.id是一样。

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

于 2009-03-21T09:13:14.367 回答
23

您可能可以添加两个外键约束(老实说:我从未尝试过),但它会坚持父行存在于两个表中。

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

                 employee       
employees_ce     ————————       employees_sn
————————————     type           ————————————
empid —————————&gt; empid <——————— empid
name               /|\          name
                    |  
                    |  
      deductions    |  
      ——————————    |  
      empid ————————+  
      name

type在员工表中将是cesn

于 2009-03-21T07:46:38.007 回答
21

其实这是我自己做的。我有一个名为“评论”的表,其中包含其他 3 个表中记录的评论。这两种解决方案实际上都无法处理您可能想要的所有内容。在你的情况下,你会这样做:

解决方案1:

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

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

  3. 在您的“扣除”表中添加一个 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 **
    

解决方案 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         

仅当列不为空时才检查完整性,因此您可以保持引用完整性。

于 2012-01-10T16:48:18.480 回答
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
于 2016-04-28T18:04:32.050 回答
2

技术上可行。您可能会在扣减和employees_sn 中引用employees_ce。但是为什么不合并employees_sn 和employees_ce?我看不出你有两张桌子的理由。没有一对多的关系。并且(不在此示例中)许多列。

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

于 2009-03-21T07:42:31.107 回答
1

对的,这是可能的。您将需要为第三张桌子定义 2 个 FK。每个 FK 指向一个表的必填字段(即每个外部表 1 个 FK)。

于 2009-03-21T07:43:41.400 回答
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 不支持这种关系,因此您必须确保您的应用程序正确管理约束(如果您有多个不同的应用程序/服务访问同一个数据库,这会变得更加麻烦)。

于 2011-05-10T21:42:03.807 回答