我遇到了如何设计一个必须有一个主键的表的问题,该主键是两个互斥表的外键。
+----------------+ +-----------------+
| 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 |
+-----------------+
共有4个实体。 PARTY可以是PERSON或BUSINESS(但不能在同一个实例中)。 PERSON可以拥有一个或多个银行账户,而一个商业也可以拥有一个或多个银行账户。
对于PERSON,只能分配1个唯一ID。
对于商家,它可以共享相同的唯一PARTY ID,因为它具有(Scheme ID,Serial No和Unique Id)的唯一组合
PARTY的主键是“唯一ID”
PERSON的主键是“唯一ID”
BUSINESS的主要密钥是“唯一身份证”,“计划代码”和“序列号”
BANK ACCOUNT的主要密钥是PERSON和BUSINESS的所有密钥的组合,“唯一ID”是唯一的常用外键,“Scheme Code”/“Serial No”是仅限BUSINESS的外键
我认为问题出在BANK ACCOUNT实体中。如果PARTY是BUSINESS,则不会出现问题,因为所有主键/外键都已填充(唯一ID,方案代码,序列号)。但是,如果PARTY是PERSON,则只会填充唯一ID,其他两个键将具有NULL值。我认为不允许使用NULL主键。
答案 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通过连接查找这些值。