MySQL基本操作整理(八)、MySQL常見約束、事務控制語言與視圖

介紹完數據類型後,接着介紹MySQL中的常見約束、事務以及視圖。本文就分別從這三個方面進行介紹。

一、常見約束

含義:約束是一種限制,用於限制表中的數據,保證表中的數據的準確和可靠性
分類:六大約束

  • PRIMARY KEY:主鍵,用於保證該字段的值具有唯一性,並且非空
  • UNIQUE:唯一,用於保證該字段的值具有唯一性,可以爲空,一個表中可以有多個唯一鍵
  • NOT NULL:非空,用於保證該字段的值不能爲空
  • DEFAULT:默認,用於保證該字段有默認值,比如性別
  • FOREIGN KEY:外鍵,用於限制兩個表的關係,用於保證該字段的值必須來自於主表的關聯列的值
    在從表添加外鍵約束,用於引用主表中某列的值
  • CHECK:檢查約束【mysql中不支持】

添加約束的時機:可以在創建表時添加;也可以在修改表時添加
約束的分類

  • 列級約束:六大約束語法上都支持,但外鍵約束沒有效果(primary key, unique, not null, defalut 4個)
  • 表級約束:除了非空、默認,其他的都支持 (primary key, unique, foreign key 3個)

列級約束與表級約束對比

類型 位置 支持的約束類型(都不考慮check) 是否可以起約束名
列級約束 列的後面 語法都支持,但外鍵沒有效果 不可以
表級約束 所有列的下面 默認和非空不支持,其他支持 可以(主鍵沒有效果)

外鍵的特點

  1. 要求在從表設置外鍵關係
  2. 從表的外鍵列的類型和主表的關聯列的類型要求一致或兼容,名稱無要求
  3. 主表的關聯列必須是一個key(一般是主鍵或唯一)
  4. 插入數據時,先插入主表,再插入從表;刪除數據時,先刪除從表,再刪除主表

語法

CREATE TABLE 表名(
	字段名 字段類型 列級約束,
	字段名 字段類型,
	表級約束
);

1. 創建表時添加約束

(1)添加列級約束

列級約束只支持:主鍵、唯一、默認、非空
案例(測試列級約束):創建stuinfo表,並添加列級約束

CREATE TABLE stuinfo(
	id INT PRIMARY KEY,#主鍵
	stuName VARCHAR(20) NOT NULL,#非空
	gender CHAR(1) CHECK(gender='男' OR gender ='女'),#檢查,可以寫,但沒有效果
	seat INT UNIQUE,#唯一
	age INT DEFAULT  18,#默認
	majorId INT REFERENCES major(id)#外鍵,表級約束中不支持
);

查看stuinfo表中的所有索引,包括主鍵、外鍵、唯一

SHOW INDEX FROM stuinfo;

(2)添加表級約束

表級約束只支持:主鍵、唯一、外鍵
語法:在各個字段的最下面添加
【constraint 約束名】 約束類型(字段名)
案例(測試表級約束):創建上述的stuinfo表,並添加表級約束

CREATE TABLE stuinfo(
	id INT,
	stuname VARCHAR(20),
	gender CHAR(1),
	seat INT,
	age INT,
	majorid INT,
	
	CONSTRAINT pk PRIMARY KEY(id),#主鍵
	CONSTRAINT uq UNIQUE(seat),#唯一鍵
	CONSTRAINT ck CHECK(gender ='男' OR gender  = '女'),#檢查,寫上也沒效果,不支持
	CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id)#外鍵	
);

(3)創建表時添加約束的通用寫法

CREATE TABLE stuinfo(
	id INT PRIMARY KEY,
	stuname VARCHAR(20) NOT NULL,
	sex CHAR(1),
	age INT DEFAULT 18,
	seat INT UNIQUE,
	majorid INT,
	CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id)
);

主鍵和唯一鍵的大對比【面試題★】

類型 保證唯一性 是否允許爲空 一個表中可以有多少個 是否允許組合
主鍵 × 至多有1個 √(不推薦)
唯一鍵 √(最多允許一個爲空) 可以有多個 √(不推薦)

2. 修改表時添加約束

語法:

1、添加列級約束
alter table 表名 modify column 字段名 字段類型 新約束;

2、添加表級約束
alter table 表名 addconstraint 約束名】 約束類型(字段名) 【外鍵的引用】;

案例:使用修改表的方式添加約束

CREATE TABLE stuinfo(
	id INT,
	stuname VARCHAR(20),
	gender CHAR(1),
	seat INT,
	age INT,
	majorid INT
);

#修改表時添加約束
#1.添加非空約束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20)  NOT NULL;
#2.添加默認約束
ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18;
#3.添加主鍵
#(1)添加列級約束
ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY;
#(2)添加表級約束
ALTER TABLE stuinfo ADD PRIMARY KEY(id);
#4.添加唯一
#(1)添加列級約束
ALTER TABLE stuinfo MODIFY COLUMN seat INT UNIQUE;
#(2)添加表級約束
ALTER TABLE stuinfo ADD UNIQUE(seat);
#5.添加外鍵
ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id); 

3. 修改表時刪除約束

五種約束的刪除方式爲:默認和非空使用modify的方式刪除、主鍵,唯一鍵和外鍵使用drop的方式刪除
案例:

#1.刪除非空約束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL;
#2.刪除默認約束
ALTER TABLE stuinfo MODIFY COLUMN age INT ;

#3.刪除主鍵
ALTER TABLE stuinfo DROP PRIMARY KEY;
#4.刪除唯一
ALTER TABLE stuinfo DROP INDEX seat;
#5.刪除外鍵
ALTER TABLE stuinfo DROP FOREIGN KEY fk_stuinfo_major;

存在外鍵時的刪除方式

  1. 級聯刪除
    1)先刪除原來的外鍵約束
    ALTER TABLE stuinfo DROP FOREIGN KEY fk_stuinfo_major;
    2)添加新的有級聯刪除的外鍵約束
    ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id) ON DELETE CASCADE;
    3)刪除從表的數據時,主表的數據自動刪除

  2. 級聯置空
    ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id) ON DELETE SET NULL;

二、事務控制語言

除了之前介紹的DQL(數據查詢語言)、DML(數據操縱語言)以及DDL(數據定義語言),現在介紹TCL(事務控制語言,Transaction Control Language)。

用通俗的語言講Spring事務 這篇文章的開頭部分,已經比較詳細地介紹了事務。下面再簡單介紹一下。

事務的特性: ACID
原子性:一個事務不可再分割,要麼都執行要麼都不執行
一致性:一個事務執行會使數據從一個一致狀態切換到另外一個一致狀態
隔離性:一個事務的執行不受其他事務的干擾
持久性:一個事務一旦提交,則會永久的改變數據庫的數據

事務的隔離級別:

級別 \ 存在問題 髒讀 不可重複讀 幻讀
read uncommitted
read committed (oracle默認級別) ×
repeatable read (mysql默認級別) × ×
serializable × × ×

查看隔離級別:select @@tx_isolation;
設置隔離結果:set global|session isolation level 隔離級別;

事務的分類:

  • 隱式事務:事務沒有明顯的開啓和結束的標記,比如insert、update、delete語句,執行語句後自動提交
  • 顯式事務:事務具有明顯的開啓和結束的標記

事務的創建步驟:
前提:必須先設置自動提交功能爲禁用,可以通過SHOW VARIABLES LIKE 'autocommit'; 查看是否開啓了自動提交
set autocommit=0;
步驟1:開啓事務
set autocommit=0;
start transaction;【可選的語句,自動開啓】
步驟2:編寫事務中的sql語句(select insert update delete 只能是這些語句,DDL語句是不支持的)
語句1;
語句2;
【savepoint 保存點節點名】
語句3;

步驟3:結束事務
commit; 提交事務
rollback; 回滾事務
rollback to 保存點名; 回滾事務到保存點

事務案例:轉賬

#開啓事務
SET autocommit=0;
START TRANSACTION;
#編寫一組事務的語句
UPDATE account SET balance = 500 WHERE username='張無忌';
UPDATE account SET balance = 1500 WHERE username='趙敏';
#結束事務
COMMIT;
#ROLLBACK;

SELECT * FROM account;

案例2:保存點的使用

SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;
SAVEPOINT a;#設置保存點
DELETE FROM account WHERE id=28;
ROLLBACK TO a;#回滾到保存點

SELECT * FROM account;

案例3:比較使用delete清空表和 truncate清空表進行回滾的區別

#delete清空的表能夠回滾
SET autocommit=0;
START TRANSACTION;
DELETE FROM account;
ROLLBACK;

#truncate清空的表不能夠回滾
SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE account;
ROLLBACK;

三、視圖

1. 視圖介紹

含義:視圖是一張虛擬表,和普通表一樣使用;視圖是mysql5.1版本後出現的新特性,是通過表動態生成的數據

使用視圖的好處

  1. 重用sql語句
  2. 簡化複雜的sql操作,不必知道它的查詢細節
  3. 保護數據,提高安全性(視圖只提供了一部分信息,原始表中的保密信息如身份證號可以不提供出來)

視圖和普通表的對比

類型 創建語法的關鍵字 是否實際佔用物理空間 使用
視圖 create view 只是保存了sql邏輯 增刪改查,只是一般不能增刪改
普通表 create table 保存了數據 增刪改查

2. 創建視圖

語法:

create view 視圖名
as
查詢語句;

案例1:使用視圖查詢姓張的學生名和專業名

CREATE VIEW v1
AS
SELECT stuname,majorname
FROM stuinfo s
INNER JOIN major m ON s.`majorid`= m.`id`;

SELECT * FROM v1 WHERE stuname LIKE '張%';

案例2:使用視圖查看每個部門的平均工資級別

#(1)創建視圖查看每個部門的平均工資
CREATE VIEW myv2
AS
SELECT AVG(salary) ag,department_id
FROM employees
GROUP BY department_id;

#(2)使用
SELECT myv2.`ag`,g.grade_level
FROM myv2
JOIN job_grades g
ON myv2.`ag` BETWEEN g.`lowest_sal` AND g.`highest_sal`;

3. 修改視圖

方式一語法:

create or replace view  視圖名
as
查詢語句;

方式二語法:

alter view 視圖名
as 
查詢語句;

案例:查詢每個工種的平均工資

CREATE OR REPLACE VIEW myv3
AS
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;

或者

alter view myv3
AS
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;

4. 刪除視圖

語法:

drop view 視圖名,視圖名, ...;

案例:

DROP VIEW emp_v1,emp_v2,emp_v3;

5. 查看視圖

DESC myv3;

SHOW CREATE VIEW myv3;

6. 更新視圖

#1.插入
INSERT INTO myv1 VALUES('張飛','[email protected]');

#2.修改
UPDATE myv1 SET last_name = '張無忌' WHERE last_name='張飛';

#3.刪除
DELETE FROM myv1 WHERE last_name = '張無忌';

具備以下特點的視圖不允許更新

(1)包含以下關鍵字的sql語句:分組函數、distinct、group by、having、union或者union all
例如,如下所示的視圖是不允許更改的:

CREATE OR REPLACE VIEW myv1
AS
SELECT MAX(salary) m,department_id
FROM employees
GROUP BY department_id;

#不允許更新
UPDATE myv1 SET m=9000 WHERE department_id=10; #該操作報錯,不允許更新

(2)常量視圖

CREATE OR REPLACE VIEW myv2
AS
SELECT 'john' NAME;

#不允許更新
UPDATE myv2 SET NAME='lucy'; #該操作報錯,不允許更新

(3)select中包含的子查詢

CREATE OR REPLACE VIEW myv3
AS
SELECT department_id,(SELECT MAX(salary) FROM employees) 最高工資
FROM departments;

#不允許更新
UPDATE myv3 SET 最高工資=100000; #該操作報錯,不允許更新

(4)含join的連接查詢

CREATE OR REPLACE VIEW myv4
AS
SELECT last_name,department_name
FROM employees e
JOIN departments d
ON e.department_id  = d.department_id;

#允許更新,不允許插入
UPDATE myv4 SET last_name  = '張飛' WHERE last_name='Whalen'; #視圖和表的數據同時都改了
INSERT INTO myv4 VALUES('陳真','xxxx');#插入失敗

(5)from一個不能更新的視圖

CREATE OR REPLACE VIEW myv5
AS
SELECT * FROM myv3;

#不允許更新
UPDATE myv5 SET 最高工資=10000 WHERE department_id=60;

(6)where子句的子查詢引用了from子句中的表

CREATE OR REPLACE VIEW myv6
AS
SELECT last_name,email,salary
FROM employees
WHERE employee_id IN(
	SELECT  manager_id
	FROM employees
	WHERE manager_id IS NOT NULL
);

#不允許更新
UPDATE myv6 SET salary=10000 WHERE last_name = 'k_ing';
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章