1. 程式人生 > 實用技巧 >MySql筆記二——約束&事務

MySql筆記二——約束&事務

一、約束

1、概念:對錶中的資料進行限定,保證資料的正確性、有效性和完整性。

2、分類:

  1. 主鍵約束:primary key
  • 含義:非空且唯一
  • 一張表只能有一個欄位為主鍵
  • 主鍵就是表中記錄的唯一標識
  1. 非空約束:not null
    • 值不能為null
  2. 唯一約束:unique
    • 值不能重複
    • MySql中唯一約束限定的列的值可以有多個null
  3. 外來鍵約束:foreign key
    • 讓表於表產生關係,從而保證資料的正確性。(阿里規範:不得使用外來鍵與級聯,一切外來鍵概念必須在應用層解決)

3、語法

1、主鍵約束語法

1、建立表時新增

在建立表時,新增主鍵約束
		create table 表名(
			id int primary key,-- 給id新增主鍵約束
			name varchar(20)
		);

2、建立表後新增

語法:
ALTER TABLE 表名 MODIFY 欄位名 欄位型別 PRIMARY KEY;

舉例:
ALTER TABLE stu MODIFY id INT PRIMARY KEY;

3、刪除主鍵

-- 錯誤 alter table stu modify id int ;
		
		ALTER TABLE 表名 DROP PRIMARY KEY;

4、自動增長

概念:如果某一列是數值型別的,使用 auto_increment 可以來完成值得自動增長

1. 在建立表時,新增主鍵約束,並且完成主鍵自增長
		create table stu(
			id int primary key auto_increment,-- 給id新增主鍵約束
			name varchar(20)
		);
		
2.建立表後新增
	ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
	
3. 刪除自動增長
	ALTER TABLE stu MODIFY id INT;

2、非空約束語法

1、建立表時新增約束

CREATE TABLE stu(
			id INT,
			NAME VARCHAR(20) NOT NULL -- name為非空
		);

2、建立表後新增約束

ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;

3、刪除非空約束

ALTER TABLE stu MODIFY NAME VARCHAR(20);

3、唯一約束

1、建立表時新增約束

CREATE TABLE stu(
			id INT,
			phone_number VARCHAR(20) UNIQUE -- 添加了唯一約束
		
		);
* 注意mysql中,唯一約束限定的列的值可以有多個null

2、建立表後新增約束

ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;

3、刪除非空約束

ALTER TABLE stu DROP INDEX phone_number;

4、外來鍵約束

1、建立表時新增約束

create table 表名(
				....
				外來鍵列
				constraint 外來鍵名稱 foreign key (外來鍵列名稱) references 主表名稱(主表列名稱)
			);

2、建立表後新增約束

ALTER TABLE 表名 ADD CONSTRAINT 外來鍵名稱 FOREIGN KEY (外來鍵欄位名稱) REFERENCES 主表名稱(主表列名稱);

3、刪除非空約束

ALTER TABLE 表名 DROP FOREIGN KEY 外來鍵名稱;

5、級聯操作

用於操作具有外來鍵關係的表,使其級聯更新或級聯刪除。(阿里規範:不得使用外來鍵與級聯,一切外來鍵概念必須在應用層解決)

1、新增級聯

LTER TABLE 表名 ADD CONSTRAINT 外來鍵名稱 
					FOREIGN KEY (外來鍵欄位名稱) REFERENCES 主表名稱(主表列名稱) ON UPDATE CASCADE ON DELETE CASCADE  ;

2、分類

  • 級聯更新:ON UPDATE CASCADE
  • 級聯刪除:ON DELETE CASCADE

二、資料庫的設計

2.1 多表之間的關係

1、多表之間的關係分類

  • 一對一(瞭解)

    如:人和身份證

    分析:一個人只有一個身份證,一個身份證只能對應一個人

  • 一對多(多對一):

    如:部門和員工

    分析:一個部門有多個員工,一個員工只能對應一個部門

  • 多對多:

    如:學生和課程

    分析:一個學生可以選擇很多門課程,一個課程也可以被很多學生選擇

2、實現關係

  • 一對一實現方式:一對一關係實現,可以在任意一方新增唯一外來鍵指向另一方的主鍵。
  • 一對多實現方式:在多的一方建立外來鍵,指向一的一方的主鍵
  • 多對多實現方式:多對多關係實現需要藉助第三張中間表。中間表至少包含兩個欄位,這兩個欄位作為第三張表的外來鍵,分別指向兩張表的主鍵

3、小練習

-- 建立旅遊線路分類表 tab_category
		-- cid 旅遊線路分類主鍵,自動增長
		-- cname 旅遊線路分類名稱非空,唯一,字串 100
		CREATE TABLE tab_category (
			cid INT PRIMARY KEY AUTO_INCREMENT,
			cname VARCHAR(100) NOT NULL UNIQUE
		);
		
		-- 建立旅遊線路表 tab_route
		/*
		rid 旅遊線路主鍵,自動增長
		rname 旅遊線路名稱非空,唯一,字串 100
		price 價格
		rdate 上架時間,日期型別
		cid 外來鍵,所屬分類
		*/
		CREATE TABLE tab_route(
			rid INT PRIMARY KEY AUTO_INCREMENT,
			rname VARCHAR(100) NOT NULL UNIQUE,
			price DOUBLE,
			rdate DATE,
			cid INT,
			FOREIGN KEY (cid) REFERENCES tab_category(cid)
		);
		
		/*建立使用者表 tab_user
		uid 使用者主鍵,自增長
		username 使用者名稱長度 100,唯一,非空
		password 密碼長度 30,非空
		name 真實姓名長度 100
		birthday 生日
		sex 性別,定長字串 1
		telephone 手機號,字串 11
		email 郵箱,字串長度 100
		*/
		CREATE TABLE tab_user (
			uid INT PRIMARY KEY AUTO_INCREMENT,
			username VARCHAR(100) UNIQUE NOT NULL,
			PASSWORD VARCHAR(30) NOT NULL,
			NAME VARCHAR(100),
			birthday DATE,
			sex CHAR(1) DEFAULT '男',
			telephone VARCHAR(11),
			email VARCHAR(100)
		);
		
		/*
		建立收藏表 tab_favorite
		rid 旅遊線路 id,外來鍵
		date 收藏時間
		uid 使用者 id,外來鍵
		rid 和 uid 不能重複,設定複合主鍵,同一個使用者不能收藏同一個線路兩次
		*/
		CREATE TABLE tab_favorite (
			rid INT, -- 線路id
			DATE DATETIME,
			uid INT, -- 使用者id
			-- 建立複合主鍵
			PRIMARY KEY(rid,uid), -- 聯合主鍵
			FOREIGN KEY (rid) REFERENCES tab_route(rid),
			FOREIGN KEY(uid) REFERENCES tab_user(uid)
		);

2.2 資料庫設計的正規化

1、概念:設計資料庫時,需要遵循的一些規範。要遵循後邊的正規化要求,必須先遵循前邊的所有正規化要求

​ 設計關係資料庫時,遵從不同的規範要求,設計出合理的關係型資料庫,這些不同的規範要求被稱為不同的正規化,各種正規化呈遞次規範,越高的正規化資料庫冗餘越小。

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

2、正規化分類

  • 第一正規化(1NF):每一列都是不可分割的原子資料項。

    • 每一列屬性都是不可再分的屬性值,確保每一列的原子性

    • 兩列的屬性相近或相似或一樣,儘量合併屬性一樣的列,確保不產生冗餘資料。

  • 第二正規化(2NF):在1NF的基礎上,非碼屬性必須完全依賴於碼(在1NF基礎上消除非主屬性對主碼的部分函式依賴)。

    • 每一行的資料只能與其中一列相關,即一行資料只做一件事。只要資料列中出現數據重複,就要把表拆分開來。

如上圖,一個人同時訂幾個房間,就會出來一個訂單號多條資料,這樣子聯絡人都是重複的,就會造成資料冗餘。我們應該把他拆開來。

  • 第三正規化(3NF):在2NF基礎上,任何非主屬性不依賴於其它非主屬性(在2NF基礎上消除傳遞依賴)。

    • 資料不能存在傳遞關係,即沒個屬性都跟主鍵有直接關係而不是間接關係。像:a-->b-->c 屬性之間含有這樣的關係,是不符合第三正規化的。

3、擴充

* 幾個概念:
		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. 碼:如果在一張表中,一個屬性或屬性組,被其他所有屬性所完全依賴,則稱這個屬性(屬性組)為該表的碼
		
					例如:該表中碼為:(學號,課程名稱)
					* 主屬性:碼屬性組中的所有屬性
					* 非主屬性:除過碼屬性組的屬性

三、事務

事務的基本介紹

1、 概念:如果一個包含多個步驟的業務操作,被事務管理,那麼這些操作要麼同時成功,要麼同時失敗。

2、操作

  • 開啟事務:start transaction;
  • 提交事務:commit;
  • 回滾事務:rollback;

3、例子

CREATE TABLE account (
			id INT PRIMARY KEY AUTO_INCREMENT,
			NAME VARCHAR(10),
			balance DOUBLE
		);
		-- 新增資料
		INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000);
		SELECT * FROM account;
		UPDATE account SET balance = 1000;
		-- 張三給李四轉賬 500 元
		
		-- 0. 開啟事務
		START TRANSACTION;
		-- 1. 張三賬戶 -500
		
		UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan';
		-- 2. 李四賬戶 +500
		-- 出錯了...
		UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi';
		
		-- 發現執行沒有問題,提交事務
		COMMIT;
		
		-- 發現出問題了,回滾事務
		ROLLBACK;

4、MySQL資料庫中事務預設自動提交

5、事務提交的兩種方式

  • 自動提交

    • mysql就是自動提交的
    • 一條DML(增刪改)語句會自動提交一次事務。
  • 手動提交:

    • Oracle 資料庫預設是手動提交事務
    • 需要先開啟事務,再提交

6、修改事務的預設提交方式

  • 檢視事務的預設提交方式:SELECT @@autocommit; -- 1 代表自動提交 0 代表手動提交
  • 修改預設提交方式: set @@autocommit = 0;

事務的ACID原則與隔離級別

1、事務的四大特徵

  • 原子性:是不可分割的最小操作單位,要麼同時成功,要麼同時失敗。
  • 永續性:當事務提交或回滾後,資料庫會持久化的儲存資料。
  • 隔離性:多個事務之間。相互獨立。
  • 一致性:事務操作前後,資料總量不變

2、事務的隔離級別

  1. 概念:多個事務之間隔離的,相互獨立的。但是如果多個事務操作同一批資料,則會引發一些問題,設定不同的隔離級別就可以解決這些問題。

  2. 存在問題

    • 髒讀:一個事務,讀取到另一個事務中沒有提交的資料
    • 不可重複讀(虛讀):在同一個事務中,兩次讀取到的資料不一樣。
    • 幻讀:一個事務操作(DML)資料表中所有記錄,另一個事務添加了一條資料,則第一個事務查詢不到自己的修改。
  3. 隔離級別

    1、read uncommitted:讀未提交

    • 產生的問題:髒讀、不可重複讀、幻讀

    2、read committed:讀已提交 (Oracle)

    • 產生的問題:不可重複讀、幻讀

    3、repeatable read:可重複讀 (MySQL預設)

    • 產生的問題:幻讀

    4、serializable:序列化

    • 可以解決所有的問題
  • 注意:隔離級別從小到大安全性越來越高,但是效率越來越低
  • 資料庫查詢隔離級別:
    • select @@tx_isolation;
  • 資料庫設定隔離級別:
    • set global transaction isolation level 級別字串;
* 演示:
		set global transaction isolation level read uncommitted;
		start transaction;
		-- 轉賬操作
		update account set balance = balance - 500 where id = 1;
		update account set balance = balance + 500 where id = 2;