我正在遵循Jeff Smith的“Implementing Table Inheritance in SQL Server”中描述的技术(这似乎是用于实现此类结构的事实上的方法)。 People
基表与其三个子类型表Students
,Teachers
,Parents
具有1:0..1的关系。传统上,这是通过将子类型表的主键定义为基表的外键来完成的。
为了强制子类型之间的排他性(防止同一个人同时成为学生和教师),作者建议将PersonTypeID
作为持久计算列添加到每个子类型表中,并将其包括在基表的外键约束。
CREATE TABLE PersonType
(
PersonTypeID INT PRIMARY KEY,
Description VARCHAR(10)
);
INSERT INTO PersonType
VALUES (1, 'Student'),
(2, 'Teacher'),
(3, 'Parent');
CREATE TABLE People
(
PersonID INT PRIMARY KEY,
PersonTypeID INT REFERENCES PersonType (PersonTypeID),
Name VARCHAR(10),
UNIQUE (PersonID, PersonTypeID)
)
CREATE TABLE Students
(
PersonID INT PRIMARY KEY,
PersonTypeID AS 1 PERSISTED, -- student
EnrollmentDate DATETIME,
FOREIGN KEY (PersonID, PersonTypeID) REFERENCES People (PersonID, PersonTypeID)
)
CREATE TABLE Teachers
(
PersonID INT PRIMARY KEY,
PersonTypeID AS 2 PERSISTED, -- teacher
HireDate DATETIME,
FOREIGN KEY (PersonID, PersonTypeID) REFERENCES People (PersonID, PersonTypeID)
)
CREATE TABLE Parents
(
PersonID INT PRIMARY KEY,
PersonTypeID AS 3 PERSISTED, -- parents
DifficultyScore INT,
FOREIGN KEY (PersonID, PersonTypeID) REFERENCES People (PersonID, PersonTypeID)
)
然而,这种方法存在许多问题:
我的假设是,通过标量函数使用检查约束来强制执行唯一性会更好。这将消除额外列和唯一索引的浪费存储,加快对基表的更新,并希望实现与复合外键更新子类表相同的性能。
CREATE TABLE People
(
PersonID INT PRIMARY KEY,
PersonTypeID INT REFERENCES PersonType (PersonTypeID),
Name VARCHAR(10)
)
CREATE FUNCTION GetPersonTypeID (@PersonID INT)
RETURNS INT
AS
BEGIN
RETURN
(
SELECT PersonTypeID
FROM People
WHERE PersonID = @PersonID
)
END;
CREATE TABLE Students
(
PersonID INT PRIMARY KEY REFERENCES People (PersonID)
CHECK (dbo.GetPersonTypeID(PersonID) = 1),
EnrollmentDate DATETIME
)
CREATE TABLE Teachers
(
PersonID INT PRIMARY KEY REFERENCES People (PersonID)
CHECK (dbo.GetPersonTypeID(PersonID) = 2),
HireDate DATETIME
)
CREATE TABLE Parents
(
PersonID INT PRIMARY KEY REFERENCES People (PersonID)
CHECK (dbo.GetPersonTypeID(PersonID) = 3),
DifficultyScore INT
)
有没有理由不采用这种方法?
答案 0 :(得分:1)
额外的存储空间实际上是最小的,如果您的人员类型列是一个tinyint(最多255种类型的人),您仍然只使用每人一个字节。因此,这不应该是决定中的一个重要因素,主要问题是标量udfs的性能明显低于外键约束。这已经过测试,结果显示在文章Scalar UDFs wrapped in CHECK constraints are very slow and may fail for multirow updates 中。
测试也包含在this SO answer
中