【问题标题】:Primary Keys are a Foreign Key of two different mutually exclusive tables主键是两个不同互斥表的外键
【发布时间】:2011-11-03 10:07:04
【问题描述】:

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

+----------------+            +-----------------+
|       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(但不能同时是两者)。一个人可以有一个或多个银行帐户,一个企业也可以有一个或多个银行帐户。

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

  3. 对于 BUSINESS,它可以共享相同的唯一 PARTY id,因为它具有(方案代码、序列号和唯一 ID)的唯一组合

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

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

  6. BUSINESS 的主键是“唯一 ID”、“方案代码”和“序列号”

  7. BANK ACCOUNT 的主键是 PERSON 和 BUSINESS 的所有键的组合,“唯一 ID”作为唯一的公共外键,“方案代码”/“序列号”是仅来自 BUSINESS 的外键.

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

【问题讨论】:

    标签: sql foreign-keys


    【解决方案1】:

    只要您保证 PARTY 与 BUSINESS/PERSON 的比例为 1:1,请让 BANK_ACCOUNT 指代 PARTY 而不是 BUSINESS 或 PERSON。

    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 可以是 BUSINESS 或 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 就变得无关紧要了。您不需要在 BANK_ACCOUNT 中为 scheme_code/serial_no 设置列。只需使用 PARTY.party_id 创建一个视图并通过连接查找这些值。

    【讨论】:

    • 您好 Simofuri,感谢您的回答。我的问题是何时 BANK_ACCOUNT for BUSINESS 将共享相同的 account_no 但具有不同的 scheme_code 和 serial_no。 PARTY 是与 BUSINESS 的一对多关系。即 BUSINESS 可以有相同的party_id,只要它与scheme_code和serial_no的组合是唯一的。
    • 例如,scheme_code '1' 下的 BUSINESS 'A' 将与 scheme_code '2' 下的 BUSINESS 'A' 共享相同的 account_no 'abc' 但 scheme_code '3' 下的 BUSINESS 'A' 将有不同的 account_no 'efg'。如果我们只将 BANK_ACCOUNT 中的 party_id 作为引用 PARTY 的 FOREIGN KEY,我们将如何确定 BUSINESS 'A' 对于 scheme_code '1'/'2' 的 account_no 'abc' 和对于 scheme_code '3' 的 account_no 'def' ?
    猜你喜欢
    • 1970-01-01
    • 2021-09-12
    • 2010-09-17
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多