2017-03-17 72 views
0

我想創建以下2個表,其中的開始日期必須在結束日期之前:根據外鍵連接的行的行值,在SQL Server中添加檢查?

CREATE TABLE ParentEntity 
(
    ID int NOT NULL IDENTITY(1,1) PRIMARY KEY,  
    StartDate date NOT NULL,  
    EndDate date NOT NULL, 
    Description varchar(255) 
); 

ALTER TABLE ParentEntity 
    ADD CHECK (DATEDIFF(day,StartDate ,EndDate) > 0) 

CREATE TABLE ChildEntity 
( 
    ID int NOT NULL IDENTITY(1,1) PRIMARY KEY,  
    Parent int NOT NULL FOREIGN KEY REFERENCES ParentEntity (ID),  
    StartDate date NOT NULL,  
    EndDate date NOT NULL, 
    Description varchar(255) 
); 

ALTER TABLE ChildEntity 
    ADD CHECK (DATEDIFF(day,StartDate ,EndDate) > 0) 

現在我想添加這個檢查:StartDate每個ChildEntity行內必須發生的EndDate對應的ParentEntity行的StartDateEndDate之間的日期間隔。

如何進行此項檢查?我不知道如何引用通過外鍵定義的行。

回答

2

我會在CHECK s而不是DATEDIFF中使用簡單的比較。

如果您想引用父表中的列的值,您不幸需要複製子級中的列。與ON UPDATE CASCADE FK可以照顧維護這些數據持續的基礎上。然後您需要決定是否希望在子表中公開這些列的存在以及它們最初是如何填充的。

所以,基本的一個是:

CREATE TABLE ParentEntity ( 
    ID int NOT NULL IDENTITY(1,1) PRIMARY KEY,  
    StartDate date NOT NULL,  
    EndDate date NOT NULL, 
    Description varchar(255), 
    constraint UQ_ParentEntity_Dates UNIQUE (ID,StartDate,EndDate) 
); 

ALTER TABLE ParentEntity 
    ADD CHECK (StartDate < EndDate) 

CREATE TABLE ChildEntity ( 
    ID int NOT NULL IDENTITY(1,1) PRIMARY KEY,  
    Parent int NOT NULL FOREIGN KEY REFERENCES ParentEntity (ID),  
    StartDate date NOT NULL,  
    EndDate date NOT NULL, 
    Description varchar(255), 
    ParentStart date NOT NULL, 
    ParentEnd date NOT NULL, 
    constraint FK_ChildParent FOREIGN KEY 
     (Parent,ParentStart,ParentEnd) references ParentEntity 
     (ID,StartDate,EndDate) ON UPDATE CASCADE 
); 

ALTER TABLE ChildEntity 
    ADD CHECK (StartDate <EndDate) 

ALTER TABLE ChildEntity 
    ADD CHECK (StartDate >=ParentStart and EndDate <= ParentEnd) 

如果要隱藏在子表中其他列的存在,你可以創建一個視圖,並提供INSTEAD OF觸發用於填充這些列。然後,您的調用者只使用視圖而不是基表。

做這件事時,你最終與父宣佈「超級鍵」(這裏IDStartDateEndDate時候才ID孤單是一個關鍵)和冗餘外鍵約束(一個上剛剛ID)。我通常會留下這個FK來記錄表格之間的「真實」FK約束。有些人可能會選擇刪除冗餘約束。

(作爲一個完整的一邊,我也建議你使用constraint條款來介紹你的所有限制,的PK,FKS,UQS和蔣介石,並藉此機會向名字他們。它使日常維護輕鬆很多。也沒有必要將CHECK約束與最初的CREATE TABLE

+0

分開約束'約束UQ_ParentEntity_Dates UNIQUE(ID,StartDate,EndDate)'的功能是什麼,因爲我已經有一個ID定義爲主鍵?簡短的檢查更優雅,我一定會使用它,並命名它們也是很好的建議。孩子只在家長更新時才更新?如果我嘗試將ChildEntity中的'ParentStart'更新爲與實際ParentEntity StartDate不同的值,會發生什麼情況?最後一個問題:我可以爲每個ParentEntity創建多個ChildEntity。我認爲你的例子是更新孩子的ID值,這不應該發生,這是正確的嗎? –

+0

@DaniëlCamps - 對不起,FK應該在'Parent,ParentStart,ParentEnd'上,而不是使用'ID'。現在更正。並且父對象的'UNIQUE'約束的目的是允許使用FK約束在父對象和子對象之間檢查所有這三個列*。 –

+0

我最終命名了所有約束,將所有約束聲明放在CREATE TABLE子句中,使用更簡單的日期檢查,我使用子父母日期檢查。 –