數據庫完整性

數據庫完整性

實體完整性

  • 實體完整性:PRIMARY KEY

    • 列級 約束條件
    CREATE TABLE Student 
    (Sno CHAR(9) PRIMARY KEY,  /* 在列級定義主碼 */
     Sname CHAR(20) NOT NULL,
     Ssex CHAR(2),
     Sdept CHAR(20)
    );
    
    • 表級約束條件
    CREATE TABLE Student
    (Sno CHAR(9),
    Sname CHAR(20) NOT NULL,
    Sage SMALLINT,
    Sdept CHAR(20),
    PRIMARY KEY (Sno)       /* 表級定義主碼 */
    )
    
    • 多個屬性構成主碼 表級約束條件
    CREATE TABLE SC
    (Sno CHAR(9) NOT NULL,
     Cno CHAR(4) NOT NULL,
     Grade SMALLINT,
     PRIMARY KEY (Sno,Cno)      /* 只能在表級定義主碼 */
     )
    
  • 實體完整性檢查和違約處理

    1. 檢查主碼值是否唯一,如果不唯一則拒絕插入或者修改
      2.檢查主碼的各個屬性是否為空,只要有一個為空就拒絕插入或修改
  • 參照完整性 FOREIGN KEY 外碼

    CREATE TABLE SC
    (Sno CHAR(9) NOT NULL,
     Cno CHAR(4) NOT NULL,
     Grade SNALLINT,
     PRIMARY KEY (Sno,Cno),                     /* 表級定義實體完整性 */
     FOREIGN KEY (Sno) REFERENCES Student(Sno), /* 表級定義參照完整性 */
     FOREIGN KEY (Cno) REFERENCES Course(Cno)   /* 表級定義參照完整性 */
    )
    
  • 參照完整性檢查和違約處理

    被參照表(如:Student) 參照表(如:SC) 違約處理
    可能破壞參照完整性 <--插入元祖 拒絕
    可能破壞參照完整性 <--修改外碼值 拒絕
    刪除元祖 --> 可能破壞參照完整性 拒絕/級聯/設置空值
    修改主碼值 --> 可能破壞參照完整性 拒絕/級聯/設置空值

    可能破壞參照完整性的情況及違約處理

    被參照表(如:Student) 參照表(如:SC) 違約處理
    可能破壞參照完整性 <--插入元祖 拒絕
    可能破壞參照完整性 <--修改外碼值 拒絕
    刪除元祖 --> 可能破壞參照完整性 拒絕/級聯/設置空值
    修改主碼值 --> 可能破壞參照完整性 拒絕/級聯/設置空值
    • 拒絕 (NO ACTION) 執行
      不允許該操作執行, 該策略一般設置為默認策略

    • 級聯 (CASCADE) 操作
      當刪除或修改被參照表(Student)的一個元祖造成了與參照表(SC)的不一致,則刪除或修改參照表中的所有造成不一致的元祖

    • 設置為空值( SET - NULL)
      當刪除或修改被參考表的一個元祖時造成了不一致,則將參照表中的所有造成不一致的元祖的對應屬性設置為空值。

      顯式說明參照完整性違約處理示例

      CREATE TABLE SC
      (Sno CHAR(9) NOT NULL,
       Cno CHAR(4) NOT NULL,
       Grade SMALLINT,
       PRIMARY KEY(Sno,Cno),  /* 在表級定義實體完整性 */
       FOREIGN KEY(Sno) references Student(Sno) /* 在表弟定義參照完整性 */
       ON DELETE CASECADE  /* 當刪除 student 表匯總的元祖時,級聯刪除 SC 表中相應的元祖 */
       ON UPDATE CASECADE,  /* 當更新 studnet 表中的 sno 時, 級聯更新 SC 表中相應的元祖 */
       FOREIGN KEY(Cno) REFERENCES Course(Cno) /* 在表級定義參照完整性 */
       ON DELETE NO ACTION /* 當刪除 course 表中的元祖造成了與 SC 表不一致時拒絕刪除 */
       ON UPDATE CASCADE /* 當更新 course 表中的 cno 時, 級聯更新 SC 表中相應的元祖 */
      );
      
  • 用戶定義完整性

    • 屬性上的約束條件的定義

      • 列值非空 (NOT NULL)
      • 列值唯一 (UNIQUE)
      • 檢查列值 是否 滿足一個布爾表達式 (CHECK)
      1. 不允許取空值
      CREATE TABLE SC
      (Sno CHAR(9) NOT NULL,    /* Sno 屬性不允許取空值 */
       Cno CHAR(4) NOT NULL,    /* Grade 屬性不允許為空 */
       Grade SMALLINT NOT NULL, /* Grade 屬性不允許取空值 */
       PRIMARY KEY (Sno, Cno)   /* 如果在表級定義實體完整性,隱含了 Sno,Cno不允許取空值則在列級不允許取空值的定義就不必寫了 */
      )
      
      
      1. 列唯一
      CREATE TABLE DEPT
      (
      Deptno NUMERIC(2),
      Dname CHAR(9) UNIQUE, /* 要求 Dname列唯一 */
      Location CHAR(10),
      PRIMARY KEY(Deptno)
      )
      
      1. 用 CHECK 短語指定列值應該滿足的條件
      CREATE TABLE Student
      (Sno CHAR(9) PRIMARY KEY,       /* 在列級定義主碼 */
      Sname CHAR(8) NOT NULL,         /* Sname 屬性不允許取空值 */
      Ssex CHAR(8) CHECK (Ssex IN ('男','女')) /* 性別屬性Ssex 只允許取'男'或'女' */
      Sage SMALLINT,
      Sdept CHAR(20)
      )
      

      SC 表的GRADE 的值在0到100之間

      CREATE TABLE SC
      (Sno CHAR(9) NOT NULL,
       Cno CHAR(4) NOT NULL,
       Grade SMALLINT CHECK (Grade >=0 AND Grade <= 100),
       PRIMARY KEY (Sno,Cno),
       FOREIGN KEY (Sno) REFERENCES Studnet(Sno),
       FOREIGN KEY (Cno) REFERENCES Course(Cno)
      )
      
    • 屬性上的約束條件檢查和違約處理

    • 元祖上的約束條件的定義
      當學生的性別是男時,名字不能以 Ms 開頭

      CREATE TABLE Student
      (Sno CHAR(9),
      Sname CHAR(8) NOT NULL,
      Ssex CHAR(2),
      Sage SMALLINT,
      PRIMARY KEY (Sno),
      CHECK (Ssex='女' OR Sname NOT LIKE 'Ms.%') /* 定義了元組中Sname 和 Ssex 兩個屬性值之間的約束條件 */
      ):
      
    • 元組上的約束條件檢查和違約處理
      當往表中插入元組或修改屬性的值時,RDBMS就檢查元組上的約束條件是否被滿足,如果不滿足則操作被拒絕執行

  • 完整性命名子句

    1. 完整性約束命名子句
      CONSTRAINT <完整性約束條件名> [PRIMARY KEY短語|FOREIGN KEY 短語|CHECK短語]

    例: 建立學生登記表 Student, 要求學號在 90000~99999之間,姓名不能取空值,年齡小于30,性別只能是“男”“女”。

        CREATE TABLE Student
    (Sno NUMERIC(6) CONSTRAINT C1 CHECK (Sno BETWEEN 90000 AND 99999),
     Sname CHAR(20) CONSTRAINT C2 NOT NULL,
     Sage NUMERIC(3) CONSTRAINT C3 CHECK (Sage < 30),
     Ssex CHAR(2) CONSTRAINT C4 CHECK (Ssex IN ('男','女')),
     CONSTRAINT StudentKey PRIMARY KEY(Sno)
    )

創建了 5 個約束 C1,C2,C3,C4 StudentKey。

例:建立教師表TEACHER 要求每個教師的應發工資不低于 3000元 應發工資實際上就是實發工資列 Sal 與 扣除 項 Deduct 之和。

    CREATE TABLE TEACHER
    (Eno NUMERIC(4) PRIMARY KEY,
    Ename CHAR(10),
    Job CHAR(8),
    Sal NUMERIC(7,2),
    Deduct NUMERIC(7.2),
    Deptno numeric(2),
    CONSTRAINT EMPFKey FOREIGN KEY (Deptno) REFERENCES DEPT(Deptno),
    CONSTRAINTS C1 CHECK(Sal + Deduct >= 3000)
    );
  1. 修改表中的完整性限制
    解除表 Student 中 性別限制

    ALTER TABLE Student DROP CONSTRAINT C4
    

    修改表 Student 中 的約束條件, 要求學號改為 900000-999999 之間,年齡由小于30 改為小于 40.

    先刪除原來的約束條件,再增加新的約束條件

    ALTER TABLE Student Drop CONSTRAINT C1;
    ALTER TABLE Student ADD CONSTRAINT C1 CHECK (Sno BETWEEN 9000 000 AND 999 999),
    ALTER TABLE Student DROP CONSTRAINT C3;
    ALTER TABLE Student ADD CONSTRAINT C3 CHECK( Sage < 40 );
    

  • 域中的完整性限制

    CREATE DOMAIN 名字 類型 CHECK語句
    

    例: 建立一個性別域,并聲明性別域的取值范圍

    CREATE DOMAIN GenderDemain CHAR(2) CHECK(VALUE IN ('男','女'));
    

    例:建立一個性別域 GenderDomain,并對其中的限制命名

    CREATE DOMAIN GenderDomain CHAR(2) CONSTRAINT GD CHECK (VALUE IN ('男','女'));
    

    例: 刪除域 GenderMain 的限制條件 GD

    ALTER DOMAIN GenderDomian DROP CONSTRAINT GD;
    

    例:在域GenderDomian 上增加限制條件 GDD

    ALTER DOMAIN GenderDomian ADD CONSTRAINT GDD CHECK (VALUE IN ('1','0'));
    

觸發器 Trigger

  • 定義觸發器

    CREATE TRIGGER <觸發器名字> 
    |BEFORE|AFTER| <觸發器事件> ON <表名>
    FOR EACH |ROW |STATEMENT|
    [WHEN <觸發條件>]
    觸發動作體
    

    1.誰可以創建觸發器?
    表的創建者
    2. 一張表可以創建無數個觸發器么?
    只能創建有限個觸發器
    3. 和觸發器關聯的表 稱為目標表
    4. 觸發事件怎么理解?
    觸發事件可以是 INSERT/DELETE/UPDATE 也可以是這幾個事件的組合,如 INSERT OR DELETE 等, UPDATE 后面還可以有 OF<觸發列...> ,即進一步指明修改哪些列時,觸發器激活。
    5. 觸發器的類型
    觸發器按照所觸發動作的間隔尺寸可以分為行級觸發器(FOR EACH ROW) 和 語句級觸發器(FOR EACH STATEMENT).
    FOR EACH ROW 凡是該row 的值發生變化,就會觸發,觸發多次
    FOR EACH STATEMENT 無論多少條數據發生變化,只觸發一次
    6. 觸發條件
    當存在 WHEN 時, 只有滿足 WHEN 后面的條件 觸發動作執行
    沒有 WHEN 條件存在時, 默認觸發動作執行。
    7.觸發動作體
    觸發動作體 既可以是一個匿名 PL/SQL 過程塊,也可以是對已創建存儲過程的調用,如果是行觸發器,在兩種情況下,用戶都可以在過程體中使用 NEW 和 OLD 引用 UPDATE/INSERT 事件之后的新值和 UPDATE/DELETE 事件之前的舊值,如果是語句級觸發器,則不能在觸發動作體中使用 NEW 或 OLD 進行引用。
    如果觸發動作體執行失敗,激活觸發器的時間就會終止執行,觸發器的目標或觸發器可能影響的其他對象不發生任何變化。

例:定義一個BEFORE 行級觸發器,為教師表 Teacher 定義完整性規則“教授的工資不得低于4000 元,如果低于4000元 自動改為4000元”。

    CREATE TRIGGER Insert_Ur_Update_Sal /* 在教室表 Teacher 上定義觸發器 */
    BEFORE INSERT OR UPDATE ON Teacher  /* 觸發事件是插入或更新操作 */
    FOR EACH ROW    /* 這是行級觸發器 */
    AS BEGIN  /* 定義觸發動作體,這是一個 PL/SQL 過程塊 */
        IF (new.pJub='教授') AND (new.Sal < 4000) THEN /* 因為是行級觸發器,可在 */
            new.Sal := 4000;  /* 過程中使用插入或更新操作后的新值 */
        END IF
    END;                    /* 觸發動作體結束 */

例:定義 AFTER 行級觸發器,當教師表 Teacher 的工資發生變化后就自動在工資變化表 Sal_log 中增加一條相應記錄

    CREATE TABLE Sal_log
    (Eno NUMERIC(4) refereace teacher(eno)
    Sal NUMERIC(7,2),
    Username char(10),
    Date TIMESTAMP
    );

    CREATE TRIGGER Insert_Sal   /* 建立了一個觸發器 */
    AFTER INSERT ON Teacher     /* 觸發器事件是 INSERT */
    FOR EACH ROW
        AS BEGIN
            INSERT INTO Sal_log VALUES(
                new.Eno, new.Sal, CURRENT_USER, CURRENT_TIMESTAMP);
            END;

    CREATE TRIGGER Update_Sal       /* 建立一個觸發器 */
        AFTER UPDATE ON Teacher     /* 觸發器事件是 UPDATE */
        FOR EACH ROW
            IF(new.Sal<>old.Sal) THEN INSERT INTO Sal_log VALUES(
                new.Eno, new.Sal, CURRENT_USER, CURRENT_TIMESTAMP);
            END IF;
        END;
  • 激活觸發器
    觸發器執行,由觸發事件激活,由數據庫服務器自動執行。

    同一張表上多個觸發器激活時遵循如下的執行順序

    1. 執行該表上的 BEFORE 觸發器
    2. 激活觸發器的 SQL 語句
    3. 執行該表上的 AFTER 觸發器
  • 刪除觸發器
    語句如下:

    DROP TRIGGER <觸發器名> ON <表名>
    

    觸發器必須是一個已經創建的觸發器,并且只能由具有相應權限的用戶刪除

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容