文章目錄
本文內容僅在 MariaDB-10.2.15 版本下驗證,其它環境下可能略有差異。
簡單來說,約束是爲了實現業務規則、保證數據的完整性,索引是爲了查詢高效,二者原本是兩個不同的東西,只是在 mysql 中實現方法有類似之處,所以經常會讓人感到迷惑。
一、約束(Constraint)
約束,是爲了實現非空、非重等常見業務規則,在定義數據時對錶或某些字段增加的特定的約束規則。
常見的約束類型有主鍵約束、唯一約束、非空約束、默認值約束、外鍵約束等。
1、主鍵約束(primary key)
- primary key,用於定義表的主鍵,是唯一確定表中每一條記錄的標識符
- 主鍵不能爲空,也不能重複
- 一張表中只能有一個主鍵
設置主鍵:
- 創建表的同時設置主鍵
create table student1 (
sid int(10) primary key, -- 對 sid 字段設置主鍵約束
sname varchar(20) not null -- 對 sname 字段設置非空約束
)
- 創建表以後,追加主鍵
create table student2(
sid int(10) not null,
sname varchar(10) not null
)
# 追加主鍵,並設置主鍵名稱
ALTER TABLE student2 ADD CONSTRAINT pks2 PRIMARY KEY(sid);
- 設置複合主鍵
- 即把多個列同時設置爲一個主鍵
create table student3 (
sid int(10) not null,
nid int(10) not null,
sname varchar(10) not null,
primary key (sid, nid) -- 定義複合主鍵
)
- 刪除主鍵:
ALTER TABLE student3 DROP PRIMARY KEY;
2、唯一性約束(unique)
- unique,設置某列數據不能重複,但可以有空值
- 一張表中可以對多個列設置 unique 約束,也可以把多個字段定義成一個 unique 約束
- 主鍵所在的列,不能使用唯一約束
區分唯一約束和主鍵約束:
- 一張表只能有一個主鍵,但可以出現多個唯一約束
- 主鍵不能爲null,唯一可以爲null
設置唯一約束:
- 在創建表的同時,設置唯一約束:
create table student4(
sid int(10) primary key ,
sname varchar(10) unique
)
- 在創建表以後,追加約束:
create table student5(
sid int(10) primary key,
sname varchar(10)
)
ALTER TABLE student5 ADD CONSTRAINT uns5
UNIQUE(sname);
- 把多個字段都設置成同一個唯一約束:
create table student6 (
sid int(10) primary key,
nid int(10) not null,
sname varchar(10) not null,
UNIQUE KEY uk6(sid, nid) -- 定義複合 unique 約束
)
刪除約束:
ALTER TABLE student6 DROP INDEX uk6;
3、默認值約束(default)
在插入操作時,當某一列沒有值時系統就自動把之前設置的默認值賦值過去。
設置默認值約束:
create table student7(
sid int(10) primary key,
sname varchar(10) not null,
age int(10) default 12 -- 設置默認值爲12
)
4、外鍵約束(foreign key)
定義:
- 如果在一張表中有一個非主鍵的字段,指向了另一張表中的主鍵。
- 每張表中可以有多個外鍵
- 通常將外鍵所在的表稱爲子表或被約束表,指向的另一個表稱爲父表或約束表或外表
- 子表中外鍵字段的取值範圍由父表決定
- 子表在進行寫操作的時候,如果外鍵字段在父表中找不到對應的匹配,操作就會失敗
- 對父表的主鍵字段進行刪和改時,如果對應的主鍵在子表中被引用,操作就會失敗
外鍵的三種約束模式:
district
: 嚴格模式, 父表不能刪除或更新一個被子表引用的記錄。
cascade
: 級聯模式,父表操作後,子表關聯的數據也跟着一起操作。
set null
: 置空模式,父表操作後,子表對應的字段被置空(前提是外鍵字段允許爲NULL)。
使用外鍵的前提:
- 表儲存引擎必須是 innodb,否則創建的外鍵無約束效果。
- 外鍵的列類型必須與父表的主鍵類型完全一致。
- 外鍵的名字不能重複。
- 已經存在數據的字段被設爲外鍵時,必須保證字段中的數據與父表的主鍵數據對應起來。
- 外鍵必須建立索引(可以爲普通、主鍵、唯一,事先不建立的話會自動創建一個普通索引)
使用外鍵的優缺點:
- 通過數據庫自身機制(而非程序員)來保證數據一致性和完整性
- 可靠性較高,但在一定程度上降低了數據庫的速度
- 當系統數據越來越多時,尤其是現在的互聯網高併發業務場景較多,若外鍵較多,會導致系統響應很慢,要儘量少用外鍵,改成用中間層控制業務規則!
"外鍵使用示例:"
--dept表
create table dept(
did int primary key,
dname varchar(10) not null unique,
)
--emp表
create table emp(
eid int primary key,
ename varchar(10) not null ,
salary float not null,
dept_id int,
foreign key(dept_id) references dept(did) --定義外鍵 dept_id 與 dept 表的 did 主鍵字段關聯
)
其實在實際工作中,用的比較多的是主鍵、非空、默認值約束,其他的很少用,複雜的業務規則儘量通過程序來控制,從而提高數據庫性能。
二、索引(index)
定義:
- 索引是一種高效獲取數據的數據結構,可以快速提高查詢速度
- 在 innoDB 引擎中使用的是
B-Tree
索引算法。
- 在 innoDB 引擎中使用的是
- 當查詢海量數據時,索引的效果尤其明顯。
- 索引是定義在列上的,有單列索引、組合索引。
索引類型
- 普通索引:
create index 索引名字 on 表名(列名)
- 唯一索引:
- 索引字段必須是唯一的,該值不能重複
create unique index 索引名 on 表(列名)
- 複合索引:
- 也叫組合索引,在多個列創建一個索引
create index myIndex on teacher2(sname, sex)
- 刪除索引:
drop index 表.索引名字
- 主鍵索引:
- 很多時候也把
PRIMARY KEY
稱爲主鍵索引,但是主鍵和索引還是兩個不同的概念。 - 可以理解爲,創建主鍵的同時,mysql 會自動對它創建索引。
- 很多時候也把
三、區別與聯繫
這裏主要說明主鍵約束、唯一性約束和索引之間的區別與聯繫。
- 概念上不同:
- 約束是爲了保證數據的完整性,索引是爲了提高查詢速度。
- 創建主鍵約束時,mysql 默認會自動創建一個索引
- 若要實現主鍵的值不重複,在每次插入新記錄時都需要檢索數據,所以爲了提高檢索速度,同時對主鍵創建索引。
- 創建唯一約束時,mysql 默認會自動創建一個唯一索引
- 跟上面的道理一樣,通過唯一索引實現唯一約束