強制執行 1 個或多個關係
在下面的er圖中(不是我的),
一個班級可以通過一個標準的聯結表有許多教師。有沒有一種方法可以使用約束來設計 Instructors/Classes 表,以確保一個 Class 必須至少有一個 Instructor?即 1 個或多個而不是 0 個或多個?所以給定 Classes.class_id=1,必須有一個 Instructors_Classes(class_id=1,instructor_id=?) 或者這是你只是使用觸發器來強制執行的東西?
作為輔助,任何人都可以提出一個好的方法來確定一個,並且只有一個講師作為一個班級的主要講師?目前我添加了一個欄位 Instructors_Classes.IsPrimary (number) 並在 (class_id, IsPrimary) 上應用了唯一約束和 IsPrimary=Null OR 1 的驗證約束,因此每個班級只有 1 位教師可以有值 1。然後,當我想獲取所有類的列表時,我可以加入 Instructors_Classes.class_id WHERE IsPrimary=1 以便獲得該類的 Instructor 的單個值。這只是感覺有點不對,但我不是數據庫人,所以我不知道是否有更傳統的方法。我想添加一個 Classes.instructor_id 欄位,但無法弄清楚如何強制它與 Instructors_Classes 表之間的連結。
真正的“一個類必須至少有一個 Instructor”約束只能在事務送出時檢查,因為首先我們需要插入 a
Classes
並且只有在至少一個Classes
存在之後我們才能在Instructors_Classes
. 不,目前大多數 DBMS 都沒有實現這樣的功能。每個語句檢查約束,此檢查不會推遲到事務送出。Postrgesql 可以推遲 FK 和其他一些約束直到送出(感謝,ypercubeᵀᴹ)。您可以實施刪除觸發器,
Instructors_Classes
以防止刪除班級的最後一位教師。但是您的第二個“班級主要講師”要求會有所幫助。添加
Classes.PrimaryInstructor
引用Instructors_Classes
可為空的。設置值後Classes.PrimaryInstructor
,此 FK 將確保(通過適當的 ON DELETE/UPDATE 操作)至少保留課程的主要講師。編輯
準確地說,FK 以上應該是複合的,還包括
Classes
PK ,create table Classes ( ... constraint FK_prim_instr foreign key (class_id, primary_instructor) references class_instructors(class_id,instructor_id) ... );
編輯 2
範例腳本
-- MS Sql Server 2014 create table classes ( class_id int not null primary key , primary_instructor int null ); create table class_instructors( class_id int not null , instructor_id int not null , constraint PK_cl_instr primary key (class_id, instructor_id) , constraint FK_class_instr foreign key (class_id) references classes (class_id) ); go alter table classes add constraint FK_Prim_instr foreign key (class_id, primary_instructor) references class_instructors(class_id, instructor_id) insert classes (class_id) values (1); insert class_instructors (class_id,instructor_id) values (1, 10),(1,20); update classes set primary_instructor = 20 where class_id = 1; select * from classes; select * from class_instructors ; -- this will fail insert class_instructors (class_id,instructor_id) values (2,10); -- this will fail too update classes set primary_instructor = 30 where class_id = 1;