2011-05-10 138 views
3

是否有一種方法可以使用SQL Server 2005定義約束,以不僅確保外鍵存在於另一個表中,而且還符合特定條件?SQL中的複雜外鍵約束

例如,假設我有兩個表:

Table A 
-------- 
Id - int 
FK_BId - int 

Table B 
-------- 
Id - int 
Name - string 
SomeBoolean - bit 

我可以定義sayd FK_BId必須指向表B的紀錄,並在表B中記錄的約束必須SomeBoolean =真的嗎?預先感謝您提供的任何幫助。

回答

4

您可以強制使用複合鍵中的業務規則上(Id, SomeBoolean),在FK_BSomeBooleanCHECK約束表A引用此,以確保它始終是TRUE。順便說一句,我建議避免BIT,而不是使用CHAR(1)進行域檢查,例如。

CHECK (SomeBoolean IN ('F', 'T')) 

表結構可能看起來像這樣:

CREATE TABLE B 
(
Id INTEGER NOT NULL UNIQUE, -- candidate key 1 
Name VARCHAR(20) NOT NULL UNIQUE, -- candidate key 2 
SomeBoolean CHAR(1) DEFAULT 'F' NOT NULL 
    CHECK (SomeBoolean IN ('F', 'T')), 
UNIQUE (Id, SomeBoolean) -- superkey 
); 

CREATE TABLE A 
(
Ib INTEGER NOT NULL UNIQUE, 
FK_BId CHAR(1) NOT NULL, 
FK_BSomeBoolean CHAR(1) DEFAULT 'T' NOT NULL 
    CHECK (FK_BSomeBoolean = 'T') 
FOREIGN KEY (FK_BId, FK_BSomeBoolean) 
    REFERENCES B (Id, SomeBoolean) 
); 
+2

我會把'A'中的列作爲計算列而不是使用檢查約束,但這只是一種品味/風格的東西。 – 2011-05-11 07:57:09

2

我認爲你要找的東西超出了外鍵範圍,但是你可以在觸發器,存儲過程或者你的代碼中進行檢查。

如果可以做,我會說你會使它成爲一個複合外鍵,使用IDSomeBoolean,但我不認爲它實際上關心什麼是價值。

+0

觸發器是保證在這樣一個複雜的情況下的數據完整性的唯一途徑。 – HLGEM 2011-05-10 18:02:03

+0

@HLGEM - 這就是我的想法,但自從我上次使用SQL Server以來已經有一段時間了。 – Shauna 2011-05-10 18:08:43

+0

@HLGEM:你可以使用超級按鍵(根據onedaywhen的答案),這是在DRI級別沒有任何代碼 – gbn 2011-05-23 16:50:46

-1

一些數據庫(我無法檢查SQL Server)您可以添加引用其他表的檢查約束。

ALTER TABLE a ADD CONSTRAINT fancy_fk 
CHECK (FK_BId IN (SELECT Id FROM b WHERE SomeBoolean)); 

我不知道’我相信這種行爲是標準的。

+0

從我正在閱讀,這是不支持SQL Server中。 – Ocelot20 2011-05-10 17:57:09

+0

試試看。 :) – 2011-05-10 18:05:03

+1

錯誤:在此上下文中不允許使用子查詢。只有標量表達式是允許的。 – Ocelot20 2011-05-10 19:41:58