mysql中的約束和索引

本文內容僅在 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 索引算法。
  • 當查詢海量數據時,索引的效果尤其明顯。
  • 索引是定義在列上的,有單列索引、組合索引。

索引類型

  • 普通索引:
    • create index 索引名字 on 表名(列名)
  • 唯一索引:
    • 索引字段必須是唯一的,該值不能重複
    • create unique index 索引名 on 表(列名)
  • 複合索引:
    • 也叫組合索引,在多個列創建一個索引
    • create index myIndex on teacher2(sname, sex)
  • 刪除索引:
    • drop index 表.索引名字
  • 主鍵索引:
    • 很多時候也把 PRIMARY KEY 稱爲主鍵索引,但是主鍵和索引還是兩個不同的概念。
    • 可以理解爲,創建主鍵的同時,mysql 會自動對它創建索引。

三、區別與聯繫

這裏主要說明主鍵約束、唯一性約束和索引之間的區別與聯繫。

  • 概念上不同:
    • 約束是爲了保證數據的完整性,索引是爲了提高查詢速度。
  • 創建主鍵約束時,mysql 默認會自動創建一個索引
    • 若要實現主鍵的值不重複,在每次插入新記錄時都需要檢索數據,所以爲了提高檢索速度,同時對主鍵創建索引。
  • 創建唯一約束時,mysql 默認會自動創建一個唯一索引
    • 跟上面的道理一樣,通過唯一索引實現唯一約束
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章