[英]Enforcing exclusivity in table inheritance: composite foreign key vs check constraint
我正在遵循Jeff Smith的“ 在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
)
有什么理由不應該使用這種方法?
實際上,額外的存儲空間很小,如果您的人員類型列是tinyint(最多255種人員),那么您仍然每人僅使用一個字節的額外空間。 因此,這不應成為決定的主要因素,主要問題是標量udf的性能明顯比外鍵約束差。 已對此進行了測試,並且用CHECK約束包裝的標量UDF中顯示的結果非常慢,並且可能無法進行多行更新 。
測試也包含在該SO答案中
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.