我有两个表,即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
假设我已经正确理解了您的情况,这就是我所说的正确方法:
从您的数据库的更高级别描述开始!您有员工,员工可以是“ce”员工和“sn”员工(无论是什么)。在面向对象的术语中,有一个类“employee”,有两个子类,分别称为“ce employee”和“sn employee”。
然后将此更高级别的描述转换为三个表:employees
、employees_ce
和 employees_sn
:
员工(身份证,姓名)
employees_ce(id, ce 特定的东西)
employees_sn(id, sn-specific stuff)
由于所有员工都是员工(呃!),因此每个员工都会在 employees
表中占一行。 “ce”员工在 employees_ce
表中也有一行,“sn”员工在 employees_sn
表中也有一行。 employees_ce.id
是 employees.id
的外键,就像 employees_sn.id
一样。
要提及任何类型的员工(ce 或 sn),请参阅 employees
表。也就是说,您遇到问题的外键应该引用该表!
您可能可以添加两个外键约束(老实说:我从未尝试过),但它会坚持父行存在于两个表中。
相反,您可能希望为您的两个员工子类型创建一个超类型,然后将外键指向那里。 (当然,假设您有充分的理由将这两种员工分开)。
employee
employees_ce ———————— employees_sn
———————————— type ————————————
empid —————————> empid <——————— empid
name /|\ name
|
|
deductions |
—————————— |
empid ————————+
name
雇员表中的 type
将是 ce
或 sn
。
LEFT JOIN
全部,如果数量足够少的话。当不使用 'employee' 基表时,无法声明主键(因为它正在引用 tableA 或 tableB 或……);现在可以了。假设拆分 employees_ce
和 employees_sn
是明智的,并注意到该假设。
其实这是我自己做的。我有一个名为“评论”的表,其中包含其他 3 个表中记录的评论。这两种解决方案实际上都无法处理您可能想要的所有内容。在你的情况下,你会这样做:
解决方案1:
在employees_ce 和employees_sn 中添加一个tinyint 字段,该字段的默认值在每个表中都不同(该字段表示“表标识符”,因此我们将它们称为tid_ce & tid_sn)使用表的PK 在每个表上创建唯一索引和表 id 字段。在您的“扣除”表中添加一个 tinyint 字段以存储外键的后半部分(表 ID)在您的“扣除”表中创建 2 个外键(您不能强制引用完整性,因为任何一个键都是有效的或其他...但绝不会同时使用:ALTER TABLE [dbo].[Deductions] WITH NOCHECK ADD CONSTRAINT [FK_Deductions_employees_ce] FOREIGN KEY([id], [fk_tid]) REFERENCES [dbo].[employees_ce] ([empid], [tid]) 不用于复制 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])参考 [dbo].[employees_sn] ([empid], [tid]) 不用于复制 GO ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_sn] GO employees_ce ------------- - empid 名称 tid khce1 王子 1 雇员_sn ---------------- empid 名称 tid khsn1 公主 2 扣除 -------------------------------- --- id tid 名称 khce1 1 金 khsn 1 2 silver ** id + tid 创建唯一索引 **
解决方案 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
仅当列不为空时才检查完整性,因此您可以保持引用完整性。
我知道这是一个长期停滞的话题,但如果有人在这里搜索,我会如何处理多表外键。使用这种技术,您没有任何 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
技术上可行。您可能会在扣减和employees_sn 中引用employees_ce。但是为什么不合并employees_sn 和employees_ce?我看不出你有两张桌子的理由。没有一对多的关系。并且(不在此示例中)许多列。
如果您对一列进行两次引用,则员工必须在两个表中都有一个条目。
对的,这是可能的。您将需要为第三张桌子定义 2 个 FK。每个 FK 指向一个表的必填字段(即每个外部表 1 个 FK)。
假设由于某种原因您必须为两种员工类型提供两个表,我将扩展 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 不支持这种关系,因此您必须确保您的应用程序正确管理约束(如果您有多个不同的应用程序/服务访问同一个数据库,这会变得更加麻烦)。