1. 程式人生 > >【資料庫】基礎知識總結

【資料庫】基礎知識總結

資料庫完整性

為了維護資料庫完整性DBMS需要提供:
1. 提供定義完整性約束條件的機制
2. 提供完整性檢查方法:一般在INSERT UPDATE DELETE語句執行後開始檢查或者在事物提交之前進行檢查
3. 違約處理機制:比如拒絕,級聯或者其他操作

實體完整性

用PRIMARY KEY進行定義,對於單屬性,實體完整性可以定義為列級約束也可以定義為表級約束;對於多個屬性構成的碼,只能定義為表級約束。

例如:
定義為列級約束(列級主碼)


    CREATE TABLE S(
        Sno CHAR(9) PRIMARY KEY,
        Sname CHAR
(20) NOT NULL, ..... );

定義為表級約束(表級主碼)


    CREATE TABLE S(
        Sno CHAR(9) ,
        Sname CHAR(20) NOT NULL,
        .....
        PRIMARY KEY(Sno)
    );

檢查和違約處理:
1. 檢查主碼值是否唯一,如果不唯一就拒絕插入或者修改(全表掃描或者在DBMS為主碼建立的索引上進行查詢,例如B+樹索引)
2. 檢查主碼值對應的各個屬性是否為空,如果存在為空的屬性,那麼拒絕插入或者修改

參照完整性

在建立表的時候使用FOREIGN KEY 定義外碼,用REFERENCES短語指定這些外碼參照哪些表的主碼。和主碼類似,外碼也同樣可以定義表級和列級參照完整性。不過感覺沒什麼區別

例如:


    CREATE TABLE SC(
    Sno CHAR(9) NOT NULL,
    Cno CHAR(4) NOT NULL,
    .....
    PRIMARY KEY(Sno, Cno),
    FOREIGN KEY (Sno) REFERENCES Sudent(Sno),
    FOREIGN KEY (Cno) REFERENCES Course(Cno),
    );

破壞參照完整性的情形以及違約處理:
1. SC表中插入一個元組但是該元組的Sno屬性在被參照表Student中是不存在的
2. SC表中更新一個元組但是該元組的Sno屬性在被參照表Student中是不存在的
3. Student表中刪除一個元組,導致參照表SC中某些元組的Sno在Student表中不存在
4. Student表中更新一個元組,導致參照表SC中某些元組的Sno在Student表中不存在

發生不一致的時候一般採取的措施是:
1. 拒絕執行
2. 級聯操作:刪除或者修改被參照表導致不滿足參照完整性的時候,級聯刪除慘遭表中所有的不一致元組
3. 設定空值(這也引起一個問題就是在定義外碼的時候是否允許外碼列為空,如果不允許為空,那麼就不能按3來處理)

至於採用哪種處理策略,可以在建表的時候顯式指定


    CREATE TABLE SC(
    Sno CHAR(9) NOT NULL,
    Cno CHAR(4) NOT NULL,
    .....
    PRIMARY KEY(Sno, Cno),
    FOREIGN KEY (Sno) REFERENCES Sudent(Sno)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    FOREIGN KEY (Cno) REFERENCES Course(Cno)
        ON DELETE NO ACTION
        ON UPDATE CASCADE,  
    );

使用者自定義完整性

根據具體應用而定義的資料必須滿足的語義要求。分類:

  1. 列值非空(NOT NULL 短語)
  2. 列值唯一(UNIQUE 短語)
  3. 檢查列值是否滿足布林表示式(CHECK 短語)

    CREATE TABLE SC(
    Sno CHAR(9) UNIQUE,
    Cno CHAR(4) NOT NULL,
    Grade SMALLINT CHECK(Grade >=0 AND Grade <=100),
    .....
    PRIMARY KEY(Sno, Cno),
    FOREIGN KEY (Sno) REFERENCES Sudent(Sno),
    FOREIGN KEY (Cno) REFERENCES Course(Cno),
    );

和前面一樣,使用者自定義完整性同樣是可以定義為列級限制也可以定義為表級限制。入上述例子就是列級使用者自定義完整性,表級使用者自定義完整新如下:


    CREATE TABLE Student(
    Sno CHAR(9) UNIQUE,
    Sname CHAR(8) NOT NULL,
    Ssex CHAR(2),
    .....
    PRIMARY KEY(Sno),
    CHECK (Ssex = '女' OR Sname NOT LIKE 'Ms.%')
    );

兩者的區別是表級限制可以定義不同屬性取值之間的限制。如上述的例子中定義了性別屬性以及姓名屬性兩者之間的約束。

約束檢查和違約處理:
一般採用拒絕執行的方式處理。

完整性命名子句

除了直接使用上述的3中完整性約束之外,SQL還提供了CONSTRAINT完整性約束命名子句,用來對完整性約束條件命名,以方便增加和刪除完整性約束。

完整性命名子句的定義:
直接看例子:


    CREATE TABLE Student(
    Sno NUMERIC(6) 
        CONSTRAINT C1 CHECK(Sno BETWEEN 90000 AND 99999),
    Sname CHAR(8) 
        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)
    );

完整性命名子句的修改:
直接刪除並重新定義即可


    ALTER TABLE Student
        DROP CONSTRAINT C1;
    ALTER TABLE Student
        ADD CONSTRAINT C1 CHECK(Sno BETWEEN 900000 AND 9999999);

觸發器

觸發器是使用者定義在關係表上的一類由事件驅動的特殊過程。定義之後,任何使用者對資料庫的增刪該操作均由DBMS自動啟用相應的觸發器。觸發器類似於約束但是比約束更加靈活。可以實現比foreign key check約束更為複雜的檢查和操作,具有更加精細和強大的資料控制能力。

觸發器例項:


    CREATE TABLE Sql_log(
    Eno NUMERIC(4) REFERENCE teacher(Eno),
    Sal NUMERIC(7, 2),
    Username CHAR(10),
    Date TIMESTAMP
    );

    CREATE TRIGGER Insert_Sal
        AFTER INSERT ON Teacher
        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
        FOR EACH ROW
        AS BEGIN
            IF(new.Sal <> old.Sal) THEN INSERT INTO Sal_log VALUES(new.Eno, new.Sal, CURRENT_USER, CURRENT_TIMESTAMP);
            END IF;
        END;

注意:
1. 表的擁有者才可以建立該表的觸發器
2. 觸發事件可以使INSERT / DELETE /UPDATE也可以是三者的組合
3. 行級觸發器

同一個表上的觸發器啟用順序:
1. 執行before觸發器-同一個表上的多個before觸發器按定義順序執行
2. 啟用觸發器的sql語句
3. 觸發器被啟用之後,只有當觸發條件為真的時候才執行觸發動作體。如果省略when觸發條件,那麼觸發動作體在觸發器被啟用之後立刻執行
4. 觸發動作體既可以是一個匿名SQL語句也可以是對已經建立的儲存過程的呼叫。

觸發器的刪除:
被刪除的觸發器必須是一個已經建立的觸發器,而且刪除者也必須有相應的使用者許可權。


    DROP TRIGGER Insert_Sql ON Teacher;

觸發器分為事前觸發和事後觸發,兩者的區別?行級觸發(FOR EACH ROW)和語句級觸發( FOR EACH STATEMENT)的區別是什麼?
事前觸發發生在事件發生之前,用驗證一些條件或者準備工作;事後觸發發生在事件發生之後,做收尾工作。事前觸發可以獲取之前的值old和新值new,事後觸發可以保證事務的完整性。
語句級觸發可以在語句執行之前或者執行之後進行,一般只執行一次,而行級觸發,觸事件根據被影響的行的數量,一般會執行多次。同時,行級觸發器可以使用new 和old來引用update/insert事件執行前後的值,但是語句級觸發是不行的。

正規化

正規化就是符合一定的級別的關係模式的集合,一般有1NF 2NF 3NF BCNF 4NF

1NF

1NF是指滿足資料庫中的每一列都是不可再分的基本資料項,是資料庫最基本的要求(同一列中不能有多個值或者出現重複屬性)。

2NF

2NF是在1NF的基礎上,消除了每一個非主屬性的部分函式依賴。通俗的講就是要求資料庫中的每一行或者每一個例項是可以唯一的被區分開(不存在多種區分方式,也就沒有了部分函式依賴)。

3NF

3NF 是在2NF的基礎上消除了非主屬性的傳遞函式依賴

BCNF

BCNF在3NF的基礎上又消除了主屬性對碼的傳遞依賴和部分依賴,也就是說BCNF消除了任何屬性(包括主屬性和非主屬性)對碼的部分依賴和傳遞依賴。
一個特殊的BCNF例子就是全碼,顯然全碼不存在非主屬性,因此至少是3NF,而且全碼也不存在傳遞和部分依賴,所以也是BCNF

BCNF是函式依賴範圍內的最佳優化,基本消除了插入和刪除異常,但是對多值依賴範圍內是無效的。

4NF

4NF限制關係模式的屬性之間不存在非平凡且非函式依賴的多值依賴(唯一允許的非平凡多值依賴是函式依賴)。

涉及到的概念:多值依賴,平凡多值依賴,函式依賴等等,直接找本書看看就可以了,確實抽象了一點點。

在多值依賴範圍內,4NF已經是優化程度最高的。

規範化過程:
1NF消除非主屬性的部分函式依賴->2NF消除非主屬性的函式依賴->3NF消除主屬性的部分函式依賴和傳遞函式依賴->BCNF消除非平凡且非函式依賴的多值依賴->4NF

檢視

檢視是從一個或者多個基本表中匯出的表,資料庫中值存放檢視的定義而不存放對應檢視的資料。檢視被定義之後就可以和基本表一樣被查詢和刪除,同時在檢視之上還可以繼續定義檢視。對檢視的更新操作(增刪改)是有一定的限制

檢視的定義:


    CREATE VIEW IS_Student
    AS
    SELECT Sno, Sname, Sage
    FROM Student
    WHERE Sdept='IS'
    WITH CHECK OPTION;

WITH CHECK OPTION表示對資料進行更新update insert delete操作的時候需要保證更新操作滿足定義檢視中的謂詞條件。也就是AS之後的子查詢。
此外,組成檢視的屬性列名要麼全部省略要麼全部指定,必須指定列名的情形:1)目標列是聚集函式或者是列表達式 2)多表連線時選擇了同名列作為檢視的欄位 3)需要在檢視中定義更合適的名字。

如上述的例項,所建立的檢視僅僅是從一個基本表中匯出,去掉了基本表的某些行某些列但是保留了主碼,此類檢視稱為是行列子集檢視


    CREATE VIEW BT_S(Sno, Sname, Sbirth)
    AS
    SELECT Sno, Sname, 2016-Sage
    FROM Student

在檢視中的資料是不儲存的,有些時候,檢視中的列是經過基本表派生出來的,這些派生列由於在資料庫中並不儲存,因此被稱為是虛擬列。帶虛擬列的檢視也被稱為是帶表示式的檢視


    CREATE VIEW S_G(Sno, Gavg)
    AS
    SELECT Sno, AVG(Grade)
    FROM SC
    GROUP BY Sno;

使用聚集函式和GROUP BY子句的查詢來定義的檢視被稱為是分組檢視

行列子集檢視是可以更新的,但是分組檢視和帶表示式的檢視一般是不可更新的。

檢視的刪除,一般刪除和級聯刪除。級聯刪除的時候,基於本檢視而定義的檢視也被刪除。

檢視消解:在進行基於檢視的查詢的時候,首先會進行有效性檢查,通過之後,把定義的子查詢和用於的查詢結合起來,轉化為等價的基本表的查詢,最後執行修正了的查詢。該轉換過程就稱為是檢視消解。

檢視消解並不一定總是成功的,尤其是非行列子集檢視,因此這類檢視的查詢儘量直接基於基本表進行。

對檢視的更新也是基於檢視消解進行的,而且檢視的更新要求更加嚴格,除了行列子集檢視是可以直接更新之外,其他檢視有些檢視理論上就被證明是無法更新的。

檢視的作用:
1. 簡化使用者操作
2. 使使用者能夠以多種角度看待同一資料
3. 檢視對於重構資料庫提供了一定程度的邏輯獨立性
4. 檢視可以對機密資料提供安全保護
5. 適當的檢視可以實現更加清晰簡潔的查詢

事務

事務是指使用者定義的一個數據庫操作序列,這些操作序列是一個不可分割的工作單位,要麼全做要麼全不做。事務的開始和結束可以由使用者進行顯示的定義和控制,如果沒有定義事務,那麼由DBMS按預設規定自動劃分事務。

事務的特性:
1. 原子性
2. 一致性:事務的執行時使資料庫從一個一致性狀態到達另外一個一致性狀態
3. 隔離性:一個事務內部的操作及使用的資料對於其他併發執行的事務而言是隔離的,也就是併發執行的各個事務之間是互不干擾的。
4. 持續性:一個事務一旦提交,對於數九的更改就是永久的。接下來的事務或者故障不應對其產生影響

事務是恢復和併發控制的基本單位
可能破壞ACID特性的場景:
1. 多個事務併發執行,不同的事務出現交叉
2. 事務在執行過程中被強行停止

其他

內連線和外連線的區別

一個查詢中涉及多個表,該查詢稱為是連線查詢。包括等值連線查詢,自然連線查詢,非等值連線查詢,自身連線查詢,外連線查詢和符合條件連線查詢。

當連線運算子為’=’的時候,稱為是等值連線,其他都是非等值連線。在等值連線中,將目標列中的重複的去掉,稱為是自然連線
查詢中的連線如果是一個表與自身進行連線,稱為是自身連線

通常的查詢中,只有滿足連線條件的元組才會輸出,如果在插敘中將主體表中不滿足條件的元組一併輸出,並且在不滿足條件的列上填NULL,這種型別的連線稱為是外連線。根據主體表的選擇的不同,尅分為左外連線(主體表為左邊關係,輸出左邊關係中不滿足連線條件的列)和右外連線(主體表為右邊關係,輸出右邊關係中不滿足連線條件的列)。

如果where子句中,有多個條件(連線條件或者其他限定條件),稱為複合條件連線
例如:


    SELECT Student.Sno, Sname
    FROM Student, SC
    WHERE Student.Sno=SC.Sno AND SC.Cno='2' AND SC.Grade>90;

連線可以使兩個表之間,也可以是多個表之間,多表之間的連線稱為是多表連線

儲存過程與函式的區別

SQL的執行需要先進行編譯然後才可以執行。大型DBMS為了提高效率,將完成特定功能的SQL語句進行編譯優化,儲存在資料庫伺服器中,使用者可以通過指定儲存過程的名字來呼叫執行。

建立:
create procedure pro_name @ [引數名] [型別]
as
begin
….
end

呼叫: exec pro_name [引數名]
刪除: drop procedure pro_name

儲存過程可以增強SQL語言的功能和靈活性,因為可以使用流程控制語句編寫,所以具有很強的靈活性,可以用於實現複雜的判斷和運算。儲存過程不是函式,兩者的區別:
1. 儲存過程可以作為獨立的部分執行,而函式可以作為查詢語句的一部分被呼叫
2. 儲存過程一般實現的功能比較複雜,而函式實現的比較有針對性
3. 函式可以巢狀在SQL中,也可以在select中使用,而儲存過程不可以
4. 函式不可以操作實體表,只能操作內建表
5. 儲存過程建立的時候就在伺服器上進行了編譯,所以速度比較快