2014-05-07 31 views
0

如果數據庫中有一對典型的「父母和孩子」方式的表,是否有強制執行的方法(不使用觸發器),每個父母只能擁有最大的四個孩子?強制子行的最大數量

因此,我們有父母表:

​​

和孩子們表:

create table dbo.Children (
    ChildID char(2) not null primary key, 
    ParentID char(2) not null references dbo.Parents (ParentID) 
    /* usw */ 
) 

而且我們填充父母表:

insert into Parents (ParentID) values ('aa'),('bb') 

我想這個插入成功:

insert into Children (ChildID,ParentID) values 
('a1','aa'),('a2','aa'),('a3','aa') 

但對於此插入失敗:

insert into Children (ChildID,ParentID) values 
('b1','bb'),('b2','bb'),('b3','bb'),('b4','bb'),('b5','bb') 

回答

4

一個辦法做到這一點,而不使用觸發器,但它是醜陋的代碼,我不知道如果我曾經建議在使用它憤怒。

該技術使用indexed view來強制約束。通常,我非常樂意使用索引視圖來強制執行約束,當然超過和超過使用觸發器來執行約束。但是這裏的問題是,違反約束時產生的錯誤消息沒有提及任何約束名稱 - 您將收到一條錯誤消息,並且必須知道錯誤消息是由「誘殺陷阱」在你的數據庫中。

但在這裏,爲您的觀賞樂趣,是認爲:

create view dbo.DRI_Parent_Child_Maximum4 
with schemabinding 
as 
    select ParentID,COUNT_BIG(*) as Cnt, 
      SUM(536870911) as Meaningless 
    from dbo.Children 
    group by ParentID 
go 
create unique clustered index IX_DRI_Parent_Child_Maximum4 
on dbo.DRI_Parent_Child_Maximum4(ParentID) 

而且它產生的二次插入錯誤消息:

Msg 8115, Level 16, State 2, Line 1 
Arithmetic overflow error converting expression to data type int. 
The statement has been terminated. 

如果不是很明顯,這是通過安排4 *一些幻數小於int可以表示的最大數量,但是5 *相同的幻數大於最大值。

所以如果有4行或更少的行,SUM()的作品,但如果你試圖有5個或更多的行,我們得到的錯誤。


這種技術甚至可以擴展到允許爲每個家長單獨配置最大數量的子女。您需要在Parents表中存儲最大值,並且還有一個查找表,該表爲每個可能的最大值存儲一個可用的幻數以用於執行該最大值。


我計算出如何昨天做的,儘管是確保有是問這個不時在做題,我找不到任何實例,因此,新的問題&答案。正如我在這個答案的頂部所說的那樣,我不確定我是否真的在生產代碼中這樣做,或者是否只是把它作爲一個可愛的訣竅。