介紹完數據類型後,接着介紹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) | 是否可以起約束名 |
---|---|---|---|
列級約束 | 列的後面 | 語法都支持,但外鍵沒有效果 | 不可以 |
表級約束 | 所有列的下面 | 默認和非空不支持,其他支持 | 可以(主鍵沒有效果) |
外鍵的特點:
- 要求在從表設置外鍵關係
- 從表的外鍵列的類型和主表的關聯列的類型要求一致或兼容,名稱無要求
- 主表的關聯列必須是一個key(一般是主鍵或唯一)
- 插入數據時,先插入主表,再插入從表;刪除數據時,先刪除從表,再刪除主表
語法:
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 表名 add 【constraint 約束名】 約束類型(字段名) 【外鍵的引用】;
案例:使用修改表的方式添加約束
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)先刪除原來的外鍵約束
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)刪除從表的數據時,主表的數據自動刪除 -
級聯置空
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版本後出現的新特性,是通過表動態生成的數據
使用視圖的好處:
- 重用sql語句
- 簡化複雜的sql操作,不必知道它的查詢細節
- 保護數據,提高安全性(視圖只提供了一部分信息,原始表中的保密信息如身份證號可以不提供出來)
視圖和普通表的對比:
類型 | 創建語法的關鍵字 | 是否實際佔用物理空間 | 使用 |
---|---|---|---|
視圖 | 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';