主键是两个不同的互斥表的外键

时间:2011-11-03 10:07:05

标签: sql foreign-keys

我遇到了如何设计一个必须有一个主键的表的问题,该主键是两个互斥表的外键。

+----------------+            +-----------------+
|       PARTY    |            + PERSON          +
+----------------+            +-----------------+
| Unique ID (PK) | -|------O|-| Unique ID (FK)  |
| Party Type     |            | some details    |
|                |            +-----------------+
|                |            
|                |            +-----------------+
|                |            | BUSINESS        |
|                |            +-----------------+
|                |            | Scheme Code (PK)|
|                | -|------O|<| Serial No (PK)  |
|                |            | Unique ID (FK)  |
|                |            | some details    |
+----------------+            +-----------------+ 

+-----------+                 +-----------------+ 
| PERSON    | -|-----------O|<| BANK ACCOUNT    | 
+-----------+                 +-----------------+           
                              | Account No (PK) |
+-----------+                 | Unique ID (FK)  |           
| BUSINESS  | -|-----------O|<| Scheme Code (FK)|
+-----------+                 | Serial No (FK)  |           
                              | some details    |
                              +-----------------+
  1. 共有4个实体。 PARTY可以是PERSON或BUSINESS(但不能在同一个实例中)。 PERSON可以拥有一个或多个银行账户,而一个商业也可以拥有一个或多个银行账户。

  2. 对于PERSON,只能分配1个唯一ID。

  3. 对于商家,它可以共享相同的唯一PARTY ID,因为它具有(Scheme ID,Serial No和Unique Id)的唯一组合

  4. PARTY的主键是“唯一ID”

  5. PERSON的主键是“唯一ID”

  6. BUSINESS的主要密钥是“唯一身份证”,“计划代码”和“序列号”

  7. BANK ACCOUNT的主要密钥是PERSON和BUSINESS的所有密钥的组合,“唯一ID”是唯一的常用外键,“Scheme Code”/“Serial No”是仅限BUSINESS的外键

  8. 我认为问题出在BANK ACCOUNT实体中。如果PARTY是BUSINESS,则不会出现问题,因为所有主键/外键都已填充(唯一ID,方案代码,序列号)。但是,如果PARTY是PERSON,则只会填充唯一ID,其他两个键将具有NULL值。我认为不允许使用NULL主键。

1 个答案:

答案 0 :(得分:0)

让BANK_ACCOUNT参考PARTY而不是BUSINESS或PERSON,只要您保证PARTY与BUSINESS / PERSON为1:1。

CREATE TABLE PARTY (
party_id INT PRIMARY KEY)

CREATE TABLE PERSON (
   person_id INT PRIMARY KEY,
   party_id INT FOREIGN KEY REFERENCES PARTY(party_id),
   ...,)

CREATE TABLE BUSINESS (
   business_id INT PRIMARY KEY,
   party_id INT FOREIGN KEY REFERENCES PARTY(party_id),
   scheme_code <TYPE>,
   serial_no <TYPE>,
   ...,)

CREATE TABLE BANK_ACCOUNT (
   account_no INT PRIMARY KEY,
   party_id INT FOREIGN KEY REFERENCES PARTY(party_id)
   ...,)

要强制执行业务规则#1,其中PARTY可以是业务或PERSON,但不能同时兼顾两者:您需要通过检查BUSINESS或PERSON中的PARTY.party_id来在触发器/程序中实现。

对于规则#2,其中PARTY与PERSON严格为1:1,在(PERSON.person_id,PERSON.party_id)或唯一索引上创建复合/多列主键。 see here

对于规则#3,与规则#2相同的解决方案。如果您可以在(BUSINESS.party_id,BUSINESS.scheme_code,BUSINESS.serial_no)上拥有复合主键,则可以省略BUSINESS.business_id。

如果您可以完成上述所有操作,则规则#7变得无关紧要。对于scheme_code / serial_no,您不需要在BANK_ACCOUNT中包含列。只需创建一个视图,并使用PARTY.party_id通过连接查找这些值。