因为您尚未将架构发布为 SQL DDL,所以我在查看这些表如何在实践中工作时遇到问题。这是我的尝试:
员工必须是人似乎是一个公平的假设,所以这很容易(猜测数据类型和域规则):
CREATE TABLE NaturalPersons
(
PersonId INTEGER NOT NULL UNIQUE
);
CREATE TABLE Employees
(
PersonId INTEGER NOT NULL UNIQUE
REFERENCES NaturalPersons (PersonId),
EmployeeID CHAR(3) NOT NULL UNIQUE
CHECK (EmployeeID LIKE '[A-Z][0-9][0-9]')
);
表名“PersonData”并没有透露太多信息,但从数据元素名称来看,似乎有些东西正在从一个人/员工转移到另一个人:
CREATE TABLE Transfers
(
FromPersonId INTEGER
REFERENCES NaturalPersons (PersonId),
FromEmployeeID CHAR(3)
REFERENCES Employees (EmployeeID),
ToPersonId INTEGER
REFERENCES NaturalPersons (PersonId),
ToEmployeeID CHAR(3)
REFERENCES Employees (EmployeeID)
);
嗯,所有NULL
能够的列意味着我们不能有 aPRIMARY KEY
但我想知道是否有钥匙......?
我们只需要一种类型的 ID 分别用于 'from' 和 'to':
ALTER TABLE Transfers ADD
CONSTRAINT only_one_from_ID
CHECK (
(FromPersonId IS NULL AND FromEmployeeID IS NOT NULL)
OR
(FromPersonId IS NOT NULL AND FromEmployeeID IS NULL)
);
ALTER TABLE Transfers ADD
CONSTRAINT only_one_to_ID
CHECK (
(ToPersonId IS NULL AND ToEmployeeID IS NOT NULL)
OR
(ToPersonId IS NOT NULL AND ToEmployeeID IS NULL)
);
我们还需要一个“常识”的业务规则来防止同一个人/员工之间的转移:
ALTER TABLE Transfers ADD
CONSTRAINT FromPersonId_cannot_be_ToPersonId
CHECK (FromPersonId <> ToPersonId);
ALTER TABLE Transfers ADD
CONSTRAINT FromEmployeeId_cannot_be_ToEmployeeId
CHECK (FromEmployeeId <> ToEmployeeId);
这是我们能做的最好的事情,但我们有几个问题:
INSERT INTO NaturalPersons (PersonId) VALUES (1), (2), (3), (4);
INSERT INTO Employees (PersonId, EmployeeID) VALUES (1, 'A11'), (2, 'B22');
-- transfer to same entity - oops!:
INSERT INTO Transfers (FromPersonId, ToEmployeeID) VALUES (1, 'A11');
-- Duplicate transfer - oops!:
INSERT INTO Transfers (FromEmployeeId, ToPersonID) VALUES (1, 'B1'); -- duplicate
INSERT INTO Transfers (FromPersonId, ToEmployeeID) VALUES ('A1', 2); -- duplicate
换句话说,将 PersonId 和 EmployeeID 混合在同一个表中,很难编写基本的数据规则。
如果我假设员工是一个人是正确的,为什么不只使用 PersonID 呢?
如果员工不是人,您可以发布您的架构(数据类型、约束等)吗?