sql運算元據庫(3)-->外來鍵約束、資料庫表之間的關係、三大正規化、多表查詢、事務

??魯阿豔??發表於2021-01-05

外來鍵約束

  • 在新表中新增外來鍵約束語法: constraint 外來鍵約束名稱 foreign key(外來鍵的欄位名稱) references 主表表名(主鍵欄位名)

  • 在已有表中新增外來鍵約束:alter table 從表表名 add constraints 外來鍵約束名稱 foreign key(外來鍵的欄位名稱) references 主表表名(主鍵欄位名)

  • 刪除外來鍵語法: alter table 從表表名 drop foreign key 外來鍵名稱;

  • 級聯操作:

    • 注意:

      在從表中,修改關聯主表中不存在的資料,是不合法的

      在主表中,刪除從表中已經存在的主表資訊,是不合法的。直接刪除主表(從表中有記錄資料關聯) 會包刪除失敗。

    • 概念: 在修改或者刪除主表的主鍵時,同時它會更新或者刪除從表中的外來鍵值,這種 動作我們稱之為級聯操作。

    • 語法:

      • 更新級聯 on update cascade 級聯更新 只能是建立表的時候建立級聯關係。當更新主表中的主鍵,從表中的外來鍵欄位會同步更新。
      • 刪除級聯 on delete cascade 級聯刪除 當刪除主表中的主鍵時,從表中的含有該欄位的記錄值會同步刪除。
    • 操作:

      -- 給從表student新增級聯操作
      create table student(
          s_id int PRIMARY key ,
          s_name VARCHAR(10) not null,
          s_c_id int,
      -- constraint  外來鍵約束名稱  foreign key(外來鍵的欄位名稱)  references 主表表名(主鍵欄位名)
      	 CONSTRAINT	stu_cour_id FOREIGN key(s_c_id)	REFERENCES	course(c_id)				-- 給s_c_id 新增外來鍵約束
      	 ON UPDATE CASCADE	ON DELETE CASCADE
      )
      
      insert into student VALUE(1,'小孫',1),(2,'小王',2),(3,'小劉',4);
      insert into student VALUE(4,'小司馬',1),(5,'小趙',1),(6,'小錢',1);
      
      -- 查詢學生表中的記錄
      select * from student;
      
      -- 級聯操作。
      -- 更新級聯  on update cascade   級聯更新 只能是建立表的時候建立級聯關係。當更新主表中的主鍵,從表中的外來鍵欄位會同步更新。
      update course set c_id = 10 where c_id = 1;
      -- 刪除級聯  on delete cascade   級聯刪除  當刪除主表中的主鍵時,從表中的含有該欄位的記錄值會同步刪除。
      
      delete from course where c_id = 10;
      

約束總結

約束名 關鍵字 描述
主鍵 primary key 唯一不為空
預設 default 插入資料,該欄位沒有賦值,系統會自動賦指定的預設值
非空 not null 該欄位不能為null(空)
唯一 unique 該欄位的值在整個表中只能出現1次
外來鍵 foreign key 從表中新增外來鍵欄位,關聯主表中的主鍵欄位

表與表之間的關係

可以分成三類:

  • 一對一的關係:一般情況下,一對一的關係基本不用,當發現兩張表是一對一的關係,合成一張表,例如:人和身份證號,學生和學生證號

  • 一對多的關係:在表關係中是最多的情況,也是最常見的,比如:部門和員工

  • 多對多:從兩個方向觀察發現都是1-n關係,比如:學生表和課程表, 企業和應聘者 雙選會

  • 操作:

    ​ 學生表、課程表 多對多關係
    ​ 使用者表 、角色表 一對多關係

    -- 建立學生表
    drop table student;
    create table student(
    		
    		s_id int PRIMARY key auto_increment, -- 主鍵約束
        s_name VARCHAR(10) not null, -- 非空約束
    		s_num int unique not null -- 唯一約束,非空約束
    
    );
    -- 建立課程表
    drop table course;
    create table course (
         
        c_id int PRIMARY key auto_increment COMMENT '課程id', -- 主鍵約束  
    		c_name VARCHAR(10) not null unique COMMENT '課程名稱' -- 唯一 非空約束
    );
    
    -- 中間表
    create table t_stu_cour (
        
         s_id int,
         c_id int,
    
         CONSTRAINT stu_id foreign key(s_id) REFERENCES student(s_id),
         CONSTRAINT cour_id foreign key(c_id) REFERENCES course(c_id)
    );
    
    -- 建立使用者表
    drop table user;
    create table user (
    
      u_id int PRIMARY key auto_increment COMMENT '使用者表主鍵id', -- 主鍵約束
      u_name VARCHAR(10) not null, -- 非空約束
      u_phone VARCHAR(11) unique, -- 唯一約束
      u_rid int, -- 需要新增的外來鍵資訊
      CONSTRAINT user_rid FOREIGN key(u_rid) REFERENCES role(r_id) 
    );
    -- 建立角色表
    drop table role;
    create table role (
    
       r_id int PRIMARY key auto_increment COMMENT '角色表主鍵id', -- 主鍵約束
       r_name VARCHAR(10) not null UNIQUE, -- 唯一約束 非空約束
       r_desc VARCHAR(255) 
    )
    -- 如果兩張表是一對多關係 設計建立時,先建立主表,再建立從表
    
  • 表與表之間關係總結

    表之間關係 關係維護、建立
    一對一 合表,互為外來鍵約束,表之間關係很少
    一對多 在從表(多的那一方)的那一方建立外來鍵,關聯主表的主鍵欄位,先建立主表,再建立從表
    多對多 建立中間表,中間表分別新增外來鍵約束關聯各自對應的的主鍵

    資料庫設計的正規化

    • 什麼是正規化?

      在設計資料庫的時候,需要遵從的規範要求,根據這些規範要求設計出合理的資料庫。這些規範被稱為正規化。

      這些正規化針對的是關係型資料庫。

      目前關係型資料庫的正規化有六種:第一正規化(1NF)、第二正規化(2NF)、第三正規化(3NF)、第四正規化(4NF)、第五正規化(完美正規化)(5NF)、巴斯-科德正規化。(BCNF)

      各種正規化呈遞次規範,越高的正規化資料庫的冗餘性就越低。

    • 前三種正規化介紹:

      • 第一正規化(1NF):資料庫中的每一列是不可分割的原子資料項。
      • 第二正規化(2NF): 在第一正規化的基礎上,非碼屬性必須完全依賴於碼(在第一正規化的基礎上消除非主屬性對碼的部分函式依賴)
        • 概念:
          1. 函式依賴:A---->B 如果通過A屬性(屬性組)的值,可以確定唯一的B屬性值,可以稱B依賴於A
          2. 完全函式依賴 A---->B 如果A是一個屬性組,則B屬性值的確定需要依賴於A屬性組中的所有屬性值
          3. 部分函式依賴 A---->B 如果A是一個屬性組,則B屬性值的確定只需要依賴於A屬性組中某一個或某一些屬性值即可。
          4. 傳遞函式依賴 A---->B B---->C 如果通過A屬性(屬性組)的值,可以唯一確定B屬性的值,在通過B屬性的值可以唯一確定C屬性的值,可以稱 C 傳遞依賴於A
          5. 碼:如果在一張表中,一個屬性或者屬性組,被其他所有屬性所完全依賴,則稱這個屬性(屬性組)為該表的碼。
            • 主屬性: 碼屬性組中的所有屬性
            • 非主屬性:除主屬性外的其他屬性
      • 第三正規化(3NF):在第二正規化的基礎上,任何非主屬性不依賴與其他的非主屬性(在2NF基礎上,消除傳遞函式依賴)
    • 三大正規化總結

      正規化 特徵
      1NF 表中的每一列具有原子性,表中的每一列不可分割
      2NF 消除部分函式依賴,一張表只做一件事
      3NF 消除傳遞函式依賴,表中的每一列都直接依賴於碼(主鍵)。不需要通過其他的欄位(列)間接依賴於主鍵

      多表連線查詢

      • 分類:內連線(顯式內連線、隱式內連式)、外連線(左外連線、右外連線)

      • 笛卡爾積現象:

        • 左表中的每條記錄和右表中的每條記錄全關聯組合,這種效果就稱之為笛卡爾積現象。
      • 消除笛卡爾積現象

        新增條件過濾,使用where條件語句,達到過濾掉無效的資料。

      • 內連線 inner join

        • 隱式內連線:省略掉內連線關鍵字 inner join
          • 語法: select 欄位列表 from 表名1,表名2,.... where 條件語句
          • 操作: select * from department ,employee where d_id = e_did;
        • 顯式內連線:使用內連線關鍵字 inner join .... on語句 inner 可以省略
          • 語法: select 欄位列表 from 表名1 [inner] join 表名2 on 條件語句
          • 操作:select * from department inner join employ on d_id = e_did;
        • 總結
          1. 查詢哪些表
          2. 確定表關聯的條件
          3. 使用連線的方式
          4. 確定查詢的欄位資訊 ,儘量少用*
      • 外連線

        • 左外連線: 使用 left [outer] join ..... on 條件語句 outer關鍵字可以省略
          • 語法: select 欄位列表 from 左表(主表) left [outer] join 右表(從表/輔表) on 條件語句。
          • 注意事項:用左表中的記錄資料去匹配右表中的記錄資料,如果符合條件的則顯示,不顯示的資料一律顯示為null。保證左表中的資料全部顯示。
          • 操作:select d.*, e. e_username from department as d left outer join employee as e on e.e_did = d.d_id;
        • 右外連線 使用 right [outer] join ..... on 條件語句 outer關鍵字可以省略
          • 語法: select 欄位列表 from 右表(主表) right [outer] join 左表(從表/輔表) on 條件語句。
          • 注意事項:用右表中的記錄資料去匹配左表中的記錄資料,如果符合條件的則顯示,不顯示的資料一律顯示為null。保證右表中的資料全部顯示。
          • select * from employ right outer join department on e_did = d_id right outer join salary on e_id = s_eid
      • 子查詢

        • 什麼是子查詢?

        • 概念:一個查詢的結果是另一個查詢的條件,形成查詢巢狀,裡面的查詢稱之為子查詢,一定要出現小括號。

        • 子查詢有三種情況:

          • 子查詢結果可以是單行單列,只有一個欄位,這一個只有一個值

          • 也可以是多行單利,只有一個欄位,這個欄位有多個值

          • 還可以是多行多列,有多個欄位,多個欄位分別有多個值。

          • 操作:

            • 第一種情況: 單行單列

              1. 語法:select 查詢欄位列表 from 表名 where 欄位 比較運算子 (子查詢);
              2. 特徵:我們可以在where的後面 使用比較運算子 > < >= <= != <>
            • 第二種情況:多行單列

              1. 語法:select 查詢欄位列表 from 表名 where 欄位 in (子查詢);

              2. 特徵:結果值是一個集合或者一個陣列,父查詢使用in運算子

              3. 操作:

                select 
                	d_name 
                from 
                	department 
                WHERE 
                	d_id 
                in (
                SELECT
                  DISTINCT e_did
                FROM 
                   employee
                WHERE
                   age > (
                 SELECT
                    avg(age)
                FROM
                   employee 
                )
                )
                
            • 第三種情況:多行多列,一般情況下我們可以作為一張虛擬表,進行關聯二次查詢,一般需要給這個虛擬表起一個別名來實現。

              • 語法:select 查詢欄位列表 from 表名 ,(子查詢) as 新表名 where 條件語句 ;
              • 特徵:多行多列不能再使用in運算子或者比較運算子,而是需要進行多表關聯,給查詢出來的多行多列起別名。
        • 子查詢總結:

          • 單行單列:只有一個值,在where後面可以使用比較運算子,作為條件
          • 多行單列:是一個集合值或者陣列值,在where後面使用的是in運算子,作為條件
          • 多行多列:大多數多列結果值是放在from後面的,作為多表關聯的。可以進行二次條件過濾。

      事務

      • ​ 什麼是事務:一個業務操作中,這個操作要麼被完全執行成功,要麼被撤銷掉。這個業務操作是一個整體,在這個整體中所有的sql語句要麼全部執行成功,要麼被回滾。(業務執行失敗)。
      • 操作: 張三給李四轉賬10000,張三的賬戶減掉1萬塊 李四的賬戶增加1萬塊
      -- 建立賬戶表
      create table account (
         
          id int PRIMARY key auto_increment, -- 主鍵id
          username VARCHAR(10) not null, -- 賬戶
          balance double -- 賬戶餘額 
      )
      
      -- 插入兩條資料
      insert into account values(null,'張三',20000),(null,'李四',20000);
      -- 張三給李四轉賬1000塊錢
      -- 先讓張三的錢減掉10000
      update account set balance = balance - 10000 where username = '張三';
      
      -- 新增一條語句
      update account set balance = balance - 10000  username = '張三';
      
      -- 再讓李四的錢增加10000
      update account set balance = balance + 10000 where username = '李四';
      
      -- 還原資料
      update account set balance = 20000;
      
      -- 查詢賬戶表
      SELECT * from account;
      
      
      • 手動操作事務:

        • 三個動作:
          • 開啟事務: start transaction;
          • 提交事務: commit;
          • 回滾事務: rollback;
      • 事務的四大特性:

        1. 原子性:這個事務是一個整體,在這個整體中,是不可分割的,在事務中所有的sql語句要麼完全執行成功,要麼都失敗。
        2. 一致性:事務在執行前和執行後資料庫中的資料狀態是一致的。轉賬:張三和李四轉賬前餘額都是20000,轉賬後,如果成功結果:張三是10000,李四是30000,如果失敗結果:張三是20000,李四也是20000。
        3. 隔離性:事務與事務之間是互不影響的,在多個事務併發執行的時候應該處於隔離的狀態。
        4. 永續性:一旦事務執行成功,對資料庫的影響是持久的。
      • 事務的隔離級別:讀未提交-->read uncommitted 讀已提交--->read committed 可重複讀 ----> repeatable read

        ​ 序列化-----> serializable 鎖表 安全性最高 效能最低

      • 由事務隔離級別引發併發訪問操作的問題:髒讀、不可重複讀、幻讀。

相關文章