1. 程式人生 > 實用技巧 >MySQL資料庫——從入門到刪庫跑路(三)

MySQL資料庫——從入門到刪庫跑路(三)

外來鍵約束

  • 在新表中新增外來鍵約束語法: 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;

事務的四大特性:

    • 原子性:這個事務是一個整體,在這個整體中,是不可分割的,在事務中所有的sql語句要麼完全執行成功,要麼都失敗。

    • 一致性:事務在執行前和執行後資料庫中的資料狀態是一致的。轉賬:張三和李四轉賬前餘額都是20000,轉賬後,如果成功結果:張三是10000,李四是30000,如果失敗結果:張三是20000,李四也是20000。

    • 隔離性:事務與事務之間是互不影響的,在多個事務併發執行的時候應該處於隔離的狀態。

    • 永續性:一旦事務執行成功,對資料庫的影響是持久的。

事務的隔離級別:讀未提交-->read uncommitted 讀已提交--->read committed 可重複讀 ----> repeatable read

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

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

備註:如果表的引擎是MyISAM,則該表無法不支援事務,最好將其改為InnoDB引擎。