約束

weixin_33670713發表於2018-07-10

主動(active)元素是一個表示式或語句,只需編寫一次,儲存在資料庫中,然後在適當的時間被執行。
關係之間的約束稱為“斷言”


外來鍵約束宣告

SQL可將關係的一個屬性或屬性組宣告為外來鍵,該外來鍵引用另一個關係(也可以是同一個關係)的屬性(組)
注意:被引用的另一個關係的屬性在它所在的關係中,必須被宣告為unique或pk

兩種方式
presC# int references movieExec(cert#)

foreign key (presC#) references movieExec(cer#)
也可以是屬性名列表

注意:presC#可以有NULL,這並不要求cert#中也要有null


維護引用完整性

DBMS會阻止在宣告瞭外來鍵約束的關係上的違法修改
但對於在被引用關係上的違法修改,設計者可在下面上個選項中進行選擇
1.預設原則(default):拒絕違法更新
2.級聯原則(cascade):被引用屬性(組)的改變被仿造到外來鍵上(A引用B,B刪A刪,B改A改)
3.置空值原則(set null):當在被引用的關係上的更新影響外來鍵值時,後者被改為空值
這些選擇可獨立地選擇刪除和修改,同外來鍵一起宣告

//presC#是關係studio中的屬性
presC# int references movieExec(cert#)
                on delete set null
                on update cascade
//刪除時置空,修改時級聯

補充:違反引用完整性的元組稱為懸浮元組(外來鍵連線運算時連不上)


延遲約束檢查

若要往studio中插入一個具有一個新的presC#的元組的話,必須要先去movieExec中插入具有對應的cert#的元組
但當迴圈約束髮生時,先插入哪個都不行
要將兩個插入操作組成一個單一的事務,並通知DBMS不要檢查其約束,直到整個事務完成執行並要提交為止
任何約束的宣告後面都可以跟上
1.deferrable:約束檢查將推遲到當前事務完成是進行
2.not deferrable:預設值,每執行一條可能違反外來鍵約束的更新操作,都會進行檢查
deferrable的後面可以更上:
1.initially deferred:檢查僅被推遲到事務提交前執行
2.initially immediate:檢查在每個語句後立刻被執行


DEFERRABLE INITIALLY IMMEDIATE
預設檢查在每個語句後立即被執行。但在需要的時候,可以隨時將約束檢查延後。
在這種情況下該選項非常有用:多數時候需要在每個語句後立即檢查約束,但偶爾有一批工作需要將約束檢查延後。
NOT DEFERRABLE
永遠無法將約束檢查延後至事務提交時


presC# int unique
          references movieExec(cert#)
          deferrable initially deferred

set constraint myConstraint deferred
set constraint myConstraint immediate


SQL的create table語句可宣告兩種約束:1.在單一屬性上的約束2.在整個元組上的約束


非空值約束

presC# int references movieExec(cert#) not null
這時候置空值原則就不能用了


基於屬性的check約束

若資料庫的修改沒有改變與約束相關的屬性,則不進行基於屬性的check約束檢查
presC# int references movieExec(cert#) check(presC#>=100000)
gender char(1) check(gender in('F','M'))
用check約束來模擬引用完整性約束是不行的
presC# int check (presC# in (select cert# from movieExec))
注意presC#不能被賦空值,這點和外來鍵約束有點不一樣
若改變movieExec關係,該變化對check不可見,違反check約束也會被執行


基於元組的check約束

check (gender='F' or name not like 'Ms.%')
類似與基於屬性的check約束,基於元組的check約束對於其它關係不可見(若條件在子查詢中提及其它關係,那個關係的改變會使得R中某些元組為假,check無法阻止這種改變)
若基於元組的檢查沒有子查詢,那這類約束總可以保持
基於元組的約束比基於屬性的更頻繁的被檢查,只要該元組的任何一個屬性被改變,而不是僅當約束中被提及屬性改變


給約束命名

name char(30) constraint nameIsKey primary key


修改約束

1.通過set constraint修改約束是否延期檢查
set constraint myConstraint deferred
set constraint myConstraint immediate
2.通過alter table
alter table movieStar drop constraint nameIsKey
已刪除的約束,就不可以再引用它的名字了

alter table movieStar add constraint nameIsKey
                 primary key(name)

加的是基於元組的約束


SQL中主動元素的最強有力的形式與特定的元組或元組的分量並不相關
這些元素被稱為觸發器和斷言,它們是資料庫模式的一部分,等同於表
DBMS必須推斷資料庫的任何更新是否影響斷言的真假


建立斷言

create assertion 斷言名 check (條件)
當斷言建立時,斷言的條件必須是真,且永遠保持是真

create assertion richPres check
              (not exists
                     (select studio.name
                       from studio,movieExec
                       where presC#=cert# and netWorth<10000000
                     )
               )

刪除斷言

drop assertion 斷言名


check約束髮生在對關係插入元組或屬性修改時,並且若有子查詢的話就不能確保成立(檢查的是一條元組)
斷言發生在對任何提及的關係做改變時,必須以某種方式聚集條件的結果(檢查的是整個關係)

相關文章