您想要的是一種防止兩個派生實體共享相同超類型實例的表繼承。
數據庫如Access和MS SQL Server不支持表繼承如PostgreSQL怎麼做,但你可以僞造它:
TABLE Users (
UserId int PRIMARY KEY IDENTITY(1,1),
UserName nvarchar(50) NOT NULL,
PasswordHash binary(32) NOT NULL, -- assuming sha256
PasswordSalt binary(8) NOT NULL
)
TABLE Parents (
UserId int NOT NULL PRIMARY KEY,
-- insert parent-specific fields here
FOREIGN KEY UserId REFERENCES Users (UserId)
)
TABLE Children (
UserId int NOT NULL PRIMARY KEY,
-- insert child-specific fields here
FOREIGN KEY UserId REFERENCES Users (UserId)
)
該模式意味着,一個Parent
或Children
實體不能沒有一個特定的存在User
實體也存在。然而,因爲Access不支持真正的表繼承它不能輕易限制UserId
值,使得只有1 Parent
或Children
行可以有該值(即可以有Parent
,並且共享相同的UserId
值Child
)。
幸運的是,在數學上是正確的(就關係代數而言),但不幸中斷了OOP的方面,因爲超類(User
)現在知道它的子類 - 但這可能是可取的情況...
......無論如何。訣竅是將一個枚舉值添加到User
的主鍵(因此它是一個組合鍵),它標識一個單一的子類,然後在每個「派生」表中添加一個常數(通過CHECK CONSTRAINT
強制執行)複合鍵組件,像這樣(使用僞SQL - 關係代數是便攜式的,但像枚舉的概念和檢查約束端口不一定到MS Access非常好):
ENUM UserType (HumanParent = 1, HumanChild = 2, Other = 3)
TABLE Users (
UserId int IDENTITY(1,1),
UserType UserType NOT NULL,
UserName nvarchar(50) NOT NULL,
PasswordHash binary(32) NOT NULL, -- assuming sha256
PasswordSalt binary(8) NOT NULL
PRIMARY KEY (UserId, UserType)
)
TABLE Parents (
UserId int NOT NULL,
UserType UserType NOT NULL,
-- insert parent-specific fields here
PRIMARY KEY (UserId, UserType)
FOREIGN KEY (UserId, UserType) REFERENCES Users (UserId, UserType)
CHECK CONSTRAINT UserType = 1
)
TABLE Children (
UserId int NOT NULL,
UserType UserType NOT NULL,
-- insert child-specific fields here
PRIMARY KEY (UserId, UserType)
FOREIGN KEY (UserId, UserType) REFERENCES Users (UserId, UserType)
CHECK CONSTRAINT UserType = 2
)
因此,在輕微的低效率的成本(即UserType
列所需的額外存儲空間以及評估CHECK約束的計算開銷),您可以確保數據的正確性。
現在有樂趣移植到訪問:)
您的數據庫設計未規範化,因爲您有多個實體表示相同的信息。 – Dai
這個數據庫意味着什麼存儲?這些實體代表什麼? – Dai
@戴基本信息關於人名,姓氏等我添加了不同版本的表格,可能更加可行,但我仍在等待反饋。 – Higeath