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

91 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
Run Code Online (Sandbox Code Playgroud)

这可能吗?

deductions
--------------
id      name
khce1   gold
khsn1   silver
Run Code Online (Sandbox Code Playgroud)

Tho*_*thy 95

假设我已经正确理解了你的场景,这就是我所说的正确方法:

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

然后你这个更高层次的描述转换为三个表:employees,employees_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是一个外键employees.id,就像employees_sn.id是.

要引用任何类型的员工(ce或sn),请参阅employees表格.也就是说,你遇到麻烦的外键应该参考那个表!

  • 你如何使ce和sn相互排斥?由于员工不能同时使用ce和sn,​​因此将其反映在数据库中是一种好习惯.我现在遇到这个问题. (16认同)
  • 您可以通过在基表和派生表中存储类型来强制员工只在一个表(和正确的表)中.创建主键id,(id,type)上的唯一键,子表的外键打开(id,type),并在每个子表上放置一个CHECK约束,使其只具有正确的类型.或者,如果您的数据库执行全局检查约束(并且没有巨大的速度惩罚),您当然可以执行NOT EXISTS检查. (12认同)

der*_*ert 22

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

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

                 employee       
employees_ce     ————————       employees_sn
————————————     type           ————————————
empid —————————> empid <——————— empid
name               /|\          name
                    |  
                    |  
      deductions    |  
      ——————————    |  
      empid ————————+  
      name
Run Code Online (Sandbox Code Playgroud)

type在员工表中将是cesn.


Lit*_*leC 19

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

解决方案1:

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

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

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

  4. 在"Deductions"表中创建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 **
    
    Run Code Online (Sandbox Code Playgroud)

解决方案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         
Run Code Online (Sandbox Code Playgroud)

仅当列不为空时才检查完整性,因此可以保持参照完整性.


小智 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)
Run Code Online (Sandbox Code Playgroud)

SO Op的例子看起来像这样

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

types
---------------------
1 employees_ce
2 employees_sn
Run Code Online (Sandbox Code Playgroud)


Sas*_*cha 2

技术上可行。您可能会在扣除中引用employees_ce 和employees_sn。但为什么不合并employees_sn和employees_ce呢?我不明白为什么你有两张桌子。没有一对多的关系。并且(不在本例中)许多列。

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