第五章 數(shù)據(jù)庫(kù)完整性

一、實(shí)體完整性

1. 定義實(shí)體的完整性

關(guān)系模型的實(shí)體完整性在 CREATE TABLE 中用 PRIMARY KEY 定義。
單屬性構(gòu)成的碼:定義為 列級(jí) | 表級(jí) 約束條件。
多個(gè)屬性構(gòu)成的碼,只能定義為 表級(jí) 約束條件。

    /* 單屬性-列級(jí) */
    CREATE TABLE Student
      (Sno CHAR(9) PRIMARY KEY, /* 在列級(jí)定義主碼 */
      Sname CHAR(20) UNIQUE,   
      Ssex CHAR(2),
      Sage SMALLINT,
      Sdept CHAR(20)
     );    
    /* 單屬性-表級(jí) */ 
    CREATE TABLE Student
      (Sno CHAR(9),
      Sname CHAR(20) UNIQUE,   
      Ssex CHAR(2),
      Sage SMALLINT,
      Sdept CHAR(20),
      PRIMARY KEY(Sno)  /* 在表級(jí)定義主碼 */
     ); 
     
     /* 屬性組 */
     CREATE TABLE SC
       (Sno CHAR(9) NOT NULL,
       Cno CHAR(4) NOT NULL,
       Grade SMALLINT,
       PRIMARY KEY(Sno, Cno) /* 在表級(jí)定義主碼 */
     );
2. 實(shí)體完整性檢查和違約處理

用PRIMARY KEY短語(yǔ)定義了關(guān)系的主碼后,每當(dāng)用戶(hù)程序?qū)颈聿迦胍粭l記錄或?qū)χ鞔a列進(jìn)行更新操作時(shí),關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)將按照實(shí)體完整性規(guī)則自動(dòng)進(jìn)行檢查。包括:
(1)檢查主碼值是否唯一,如果不唯一則拒絕插入或修改;
(2)檢查主碼的各個(gè)屬性是否為空,只要有一個(gè)為空就拒絕插入或修改。
關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)一般都在主碼上自動(dòng)建立一個(gè)索引,如B+樹(shù)索引,提高查找表中是否已存在主碼的效率。

二、參照完整性

1. 定義參照完整性

關(guān)系模型的參照完整性在 CREATE TABLE 中用 FOREIGN KEY 短語(yǔ)定義哪些列為外碼,用 REFERENCES 短語(yǔ)指明這些外碼參照哪些表的主碼。

    /* 建立學(xué)生選課表SC */
    CREATE TABLE SC
      (Sno CHAR(9),
      Cno CHAR(4),
      Grade SMALLINT,
      PRIMARY KEY(Sno,Cno),  /* 主碼由兩個(gè)屬性構(gòu)成,必須作為表級(jí)完整性進(jìn)行定義 */
      FOREIGN KEY(Sno) REFERENCE Student(Sno),
            /* 表級(jí)完整性約束條件,Sno是外碼,被參照表是Student */
      FOREIGN KEY(Cno) REFERENCE Course(Cno)
            /* 表級(jí)完整性約束條件,Cno是外碼,被參照表是Course */
     );
2. 參照完整性檢查和違約處理

參照完整性將兩個(gè)表中的相應(yīng)元組聯(lián)系起來(lái)了。因此,對(duì)被參照表和參照表進(jìn)行增、刪、改操作時(shí)有可能破壞參照完整性,必須進(jìn)行檢查以保證這兩個(gè)表的相容性。

被參照表(如Student) 參照表(如SC) 違約處理
可能破壞參照完整性 ← 插入元組 拒絕
可能破壞參照完整性 ← 修改外碼值 拒絕
刪除元組 → 可能破壞參照完整性 拒絕/級(jí)聯(lián)刪除/設(shè)置為空值
修改主碼值 → 可能破壞參照完整性 拒絕/級(jí)聯(lián)刪除/設(shè)置為空值

(1)拒絕(NO ACTION)執(zhí)行:一般是默認(rèn)。
(2)級(jí)聯(lián)(CASCADE)操作 :當(dāng)刪除或修改被參照表(Student)的一個(gè)元組導(dǎo)致與參照表(SC)不一致時(shí),刪除或修改參照表中的所有導(dǎo)致不一致的元組。
(3)設(shè)置為空值:如專(zhuān)業(yè)表中某個(gè)元組(專(zhuān)業(yè)號(hào)為12)被刪除,學(xué)生表中專(zhuān)業(yè)號(hào)=12的所有元組的專(zhuān)業(yè)號(hào)設(shè)置為空值。

    /* 參照完整性違約處理-系統(tǒng)默認(rèn)拒絕,也可顯式說(shuō)明其他處理策略 */
    CREATE TABLE SC
      (Sno CHAR(9),
      Cno CHAR(4),
      Grade SMALLINT,
      PRIMARY KEY(Sno,Cno),  /* 表級(jí)完整性定義,Sno、Cno都不能取空值 */
      FOREIGN KEY(Sno) REFERENCE Student(Sno) /* 表級(jí)完整性約束條件 */
            ON DELETE CASCADE
                            /* 當(dāng)刪除Student表中元組時(shí),級(jí)聯(lián)刪除SC表中對(duì)應(yīng)元組 */
            ON UPDATE CASCADE,
                            /* 當(dāng)更新Student表中的Sno時(shí),級(jí)聯(lián)更新SC表中對(duì)應(yīng)元組 */
      FOREIGN KEY(Cno) REFERENCE Course(Cno)
            ON DELETE NO ACTION
                            /* 當(dāng)刪除Course表中元組造成與SC表不一致時(shí),拒絕刪除 */
            ON UPDATE CASCADE
                            /* 當(dāng)更新Course表中的Cno時(shí),級(jí)聯(lián)更新SC表中對(duì)應(yīng)元組 */
     );

三、用戶(hù)定義的完整性

1. 屬性上的約束條件

在 CREATE TABLE 中定義屬性同時(shí),進(jìn)行屬性值限制。

  • 列值非空 ( NOT NULL )
  • 列值唯一 ( UNIQUE )
  • 檢查列值是否滿足一個(gè)條件表達(dá)式( CHECK短語(yǔ) )
    /* Student表的Ssex只允許取"男"或"女" */
    CREATE TABLE Student
      (Sno CHAR(9) PRIMARY KEY,
      Sname CHAR(20) UNIQUE,   
      Ssex CHAR(2) CHECK(Ssex IN ('男', '女')), /* 性別屬性只能是男或女 */
      Sage SMALLINT,
      Sdept CHAR(20)
     );   
    /* SC表的Grade值在0和100之間 */
    CREATE TABLE SC
      (Sno CHAR(9),
      Cno CHAR(4),
      Grade SMALLINT CHECK(Grade >= 0 AND Grade <= 100), /* Grade取值0-100 */
      PRIMARY KEY(Sno,Cno),  
      FOREIGN KEY(Sno) REFERENCE Student(Sno),
      FOREIGN KEY(Cno) REFERENCE Course(Cno)
     );    
2. 元組上的約束條件

在 CREATE TABLE 中定義元組級(jí)的限制,可以設(shè)置不同屬性之間的取值的相互約束條件。

    /* 當(dāng)學(xué)生性別是男時(shí),名字不能以Ms.打頭 */
    CREATE TABLE Student
      (Sno CHAR(9) PRIMARY KEY,
      Sname CHAR(20) UNIQUE,   
      Ssex CHAR(2), 
      Sage SMALLINT,
      Sdept CHAR(20),
      CHECK (Ssex = '女' OR Sname NOT LIKE 'Ms.%')
     ); /* 定義了元組中 Sname 和 Ssex 兩個(gè)屬性值之間的約束條件 */

四、完整性約束命名子句

1. 完整性約束命名子句

SQL 在 CREATE TABLE 中還提供了完整性約束命名子句 CONSTRAINT,用來(lái)對(duì)完整性約束條件命名,從而靈活地增加、刪除一個(gè)完整性約束條件。
完整性約束條件包括:NOT NULL、UNIQUE、PRIMARY KEY、FOREIGN KEY、CHECK短語(yǔ)等。

    /* 完整性約束命名子句格式 */
    CONSTRAINT <完整性約束條件名><完整性約束條件>
    
    /* 建立學(xué)生登記表,要求學(xué)號(hào)在90000-99999之間,姓名非空,年齡小于30,性別取男或女 */
    CREATE TABLE Student
      (Sno NUMERIC(6)
          CONSTRAINT C1 CHECK (Sno BETWEEN 90000 AND 99999),
      Sname CHAR(20)
          CONSTRAINT C2 NOT NULL,   
      Ssex NUMERIC(3)
          CONSTRAINT C3 CHECK (Ssex IN ('男', '女')),
      Sage SMALLINT
          CONSTRAINT C4 CHECK (Sagr < 30),
          CONSTRAINT StudentKEY PRIMARY KEY (Sno)
     );
2. 修改表中的完整性限制

可以使用 ALTER TABLE 語(yǔ)句修改表中的完整性限制:先刪除原約束條件,再增加新的約束條件。

    /* 修改年齡限制為小于40歲 */    
    ALTER TABLE Student
        DROP CONSTRAINT C4; /* 去掉年齡限制 */
    ALTER TABLE Student
        ADD CONSTRAINT C4 CHECK (Sage < 40); /* 新增年齡限制小于40 */

*五、域中的完整性限制

域是一組具有相同數(shù)據(jù)類(lèi)型的集合。SQL 可以用 CREATE DOMAIN 語(yǔ)句建立一個(gè)域以及該域應(yīng)該滿足的完整性約束條件,然后就可以用域來(lái)定義屬性。
這樣定義的優(yōu)點(diǎn):數(shù)據(jù)庫(kù)中不同屬性來(lái)自同一個(gè)域,當(dāng)域上的完整性約束條件改變時(shí)只要修改域的定義即可,不必一一修改域上的各個(gè)屬性。

    /* 建立性別域,約束條件GD */
    CREATE DOMAIN GenderDomain CHAR(2)
        CONSTRAINT GD CHECK ( VALUE IN('男', '女'));
    /* 刪除性別域的限制GD */
    ALTER DOMAIN GenderDomain
        DROP CONSTRAINT GD;
    /* 增加性別域的限制GDD */
    ALTER DOMAIN GenderDomain 
        ADD CONSTRAINT GDD CHECK ( VALUE IN('1', '0'));
    

六、斷言

CREATE ASSERTION語(yǔ)句,來(lái)指定更具一般性的約束,可以定義涉及多個(gè)表或聚集操作的比較復(fù)雜的完整性約束。

1. 創(chuàng)建斷言
    /* 創(chuàng)建斷言的語(yǔ)句格式 */
    CREATE ASSERTION <斷言名> <CHECK 子句>
    
    /* 限制數(shù)據(jù)庫(kù)課程最多60名學(xué)生選修 */
    /* 每當(dāng)學(xué)生選課時(shí),將在SC表插入一條元組,ASSE_SC_DB_NUM斷言會(huì)被觸發(fā)檢查,若選修
       數(shù)據(jù)庫(kù)課程人數(shù)超過(guò)60人,CHECK子句返回值為假,對(duì)SC表的插入操作被拒絕 */
    CREATE ASSERTINO ASSE_SC_DB_NUM
          CHECK( 60 >= (SELECT count(*)
                 FROM Course, SC
                 WHERE Course.Cno = SC.Cno AND Course.Cname = '數(shù)據(jù)庫(kù)')
                );
                
    /* 限制每個(gè)學(xué)期每門(mén)課程最多60名學(xué)生選修 */
    ALTER TABLE SC ADD TERM DATE; /* SC表新增TERM屬性,類(lèi)型為DATE */
    CREATE ASSERTION ASSE_SC_CNUM
        CHECK( 60 >= ALL(SELECT count(*) 
                         FROM SC 
                         GROUP by Cno,TERM));
2. 刪除斷言
    DROP ASSERTION <斷言名>;

七、觸發(fā)器

觸發(fā)器又叫事件-條件-動(dòng)作規(guī)則,是用戶(hù)定義在關(guān)系表上的一類(lèi)由事件驅(qū)動(dòng)的特殊過(guò)程。任何用戶(hù)對(duì)表的增、刪、改操作均由服務(wù)器自動(dòng)激活相應(yīng)的觸發(fā)器,在關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)核心層進(jìn)行集中的完整性控制。

1. 定義觸發(fā)器
    /* 一般格式 */
    CREATE TRIGGER <觸發(fā)器名>  /* 每當(dāng)觸發(fā)事件發(fā)生時(shí),該觸發(fā)器被激活 */
    {BEFORE|AFTER} <觸發(fā)事件> ON <表名> 
                                /* 指明觸發(fā)器激活的時(shí)間是在執(zhí)行觸發(fā)事件前或后 */
    REFERENCING NEW|OLD ROW AS <變量> /* REFERENCING 指出引用的變量 */
    FOR EACH{ROW|STATEMENT}           /* 定義觸發(fā)器的類(lèi)型:行級(jí)|語(yǔ)句級(jí),指明動(dòng)作體執(zhí)行頻率 */
    [WHEN <觸發(fā)條件>] <觸發(fā)動(dòng)作體> /* 僅當(dāng)觸發(fā)條件為真時(shí)才執(zhí)行觸發(fā)動(dòng)作體 */
    
    
    /* 當(dāng)對(duì)表SC的Grade屬性修改時(shí),若分?jǐn)?shù)增加了10%,則將此次操作記錄到另一個(gè)表SC_U中 */
    CREATE TRIGGER SC_T
    AFTER UPDATE OF Grade ON SC /* 觸發(fā)事件為更新SC表上的Grade列*/
                                /* AFTER是觸發(fā)的時(shí)機(jī),對(duì)SC的Grade屬性修改后觸發(fā)下面規(guī)則*/
    REFERENCING
        OLDROW AS OldTuple,   /* 舊分?jǐn)?shù) */
        NEWROW AS NewTuple    /* 新分?jǐn)?shù) */
    FOR EACH ROW              /* 行級(jí)觸發(fā)器,每執(zhí)行一次Grade的更新,下面的規(guī)則就執(zhí)行一次 */
    WHEN(NewTuple.Grade >= 1.1 * OldTuple.Grade)   /* 觸發(fā)條件,為真才執(zhí)行 */
    INSERT INTO SC_U(Sno, Cno, OldGrade, NewGrade)  /* 觸發(fā)動(dòng)作體,插入到新表中*/
    VALUES(OldTuple.Sno, OldTuple.Cno, OldTuple.Grade, NewTuple.Grade)
2. 激活觸發(fā)器

觸發(fā)器的執(zhí)行是由觸發(fā)事件激活,并由數(shù)據(jù)庫(kù)服務(wù)器自動(dòng)執(zhí)行的。
同一個(gè)表上的多個(gè)觸發(fā)器激活時(shí)遵循如下的執(zhí)行順序:
(1)執(zhí)行該表上的BEFORE觸發(fā)器;
(2)激活觸發(fā)器的SQL語(yǔ)句;
(3)執(zhí)行該表上的AFTER觸發(fā)器。

3. 刪除觸發(fā)器
    DROP TRIGGER <觸發(fā)器名> ON <表名>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容