1. 程式人生 > 其它 >mysql 資料庫約束條件與索引

mysql 資料庫約束條件與索引

目錄

一 :mysql 的約束條件

1 什麼是約束

約束是一種限制,它通過對錶的行或列的資料做出限制,來確保表的資料的完整性、唯一性。真正約束欄位的是資料型別,但是資料型別約束很單一,需要有一些額外的約束,更好的保證資料的合法性,從業務邏輯角度保證資料的正確性


2 常見的約束條件

mysql 常見的額外約束條件有4 類6項

  1. Null 空值設定,:非空約束(not null)
  2. Key 鍵值設定: 唯一性約束 (unique) ,主鍵約束(primary key)PK, 外來鍵約束(foreign key)FK
  3. Default 預設設定:預設值約束 (default)
  4. Extra 額外設定:自增約束(auto_increment)

3 約束條件的新增方式

3.1 在建立新的表時候新增約束條件

create table 表名(欄位1 數值型別 約束條件, 欄位2 資料型別 約束條件);

eg: 
create table class(id int not null , name char(20) not null );  
#設定id 欄位和 name 欄位值 允許為null

3.2 使用change修改表的欄位時新增或刪除,修改,約束條件

alter table 表名 change 舊的表字段 新的表字段 資料型別 約束條件

eg:
alter table  class change  id  id int null;   
#修改id 欄位值 允許為null

當新舊錶欄位,值型別相同時,就是對約束條件的操作。

舊欄位沒有約束條件,如果值型別後面加了約束條件,則是為該欄位新增約束條件

舊欄位有約束條件,如果值型別後面跟了新的約束條件,則是為該欄位修改約束條件

舊欄位有約束條件,如果值型別後面沒有加約束條件,則是為該欄位刪除約束條件


3.3 使用modify 修改表字段屬性時,新增,修改,刪除 約束條件

alter table 表名 modify 表字段 資料型別 約束條件

eg
alter table class  modify  name char(20)  null;  
#修改name 欄位值 允許為null


4 非空約束(not null)

此項有兩個值 null 和 not null ,預設是null 。但是當欄位為空時,資料無法參與運算。

非空約束(not null ) 確保當前列的值不為空值。

所有型別的值都可以時null,包括int,float 等資料型別

當複製時,單引號'' 或雙引號"" 裡什麼都沒有時,此時表示是0個字元,而不是null,因為nul表示沒有賦值


4.1 在新建表時新增not null

 create  table class(id int , student char(20) not null)

4.2 在建立表之後,修改欄位的型別,新增not null 約束

(注意,當存在表記錄時,修改為not null 的欄位的值不可以存在空值)

alter table class  change id  id int not null ;

4.3 刪除非空約束

#將 id 欄位的not null 改回null
alter table class  change id  id int ;


4.4 null 和 not null 的效果

#向 class 表的 student 欄位新增值 'zhangsan‘ ,id 欄位不進行賦值,則預設為null
insert into class(student) value('zhangsan');   

select * from class;


#向class 表中新增表記錄,但是隻給id欄位賦值,不給student欄位賦值,則新增失敗。
insert into class(id) value(1);  


#向class 表中插入表記錄,id欄位賦值為2 
#student欄位值雖然單引號’‘裡什麼都沒有,但是代表的是0字元,而不是null。因為null表示的是沒有進行賦值
insert into class   value( 2,'');



5 唯一性約束(unique)(也是唯一性索引)

唯一約束是指定table的列或列組合不能重複,保證資料的唯一性。

唯一約束不允許出現重複的值,但是可以為多個null。

同一個表可以有多個唯一約束,多個列組合的約束。

在建立唯一約束時,如果不給唯一約束名稱,就預設和列名相同。

唯一約束不僅可以在一個表內建立,而且可以同時多表建立組合唯一約束。


5.1 建立表時設定唯一索引

方法一:在設定欄位名和資料屬性時,就新增唯一索引

create table 表名(欄位名1 資料型別1 約束條件,....);

#建立class 表,將id 欄位和 id_card 欄位 值設定為unique唯一性約束,不允許欄位值重複
create table class1(id int unique,name char(20),id_card bigint unique);

方法二: 在設定完欄位名和屬性後,在最後在新增唯索引項

create table 表名(欄位名1 資料型別1,欄位名2 資料型別2,unique(欄位名1,欄位名2...));

create  table class2(id int ,name char(20), unique(id));
#將id 欄位設定為unqiue。
#如果想象設定多個,unique() 括號中填寫過個欄位名,以逗號分隔。如unique(id,name)

5.2 在建立表之後,修改表屬性,新增唯一性約束

方法一

create unique index 索引名 on 表名(列名);

#為class 表的id 欄位建立唯一鍵
create unique  index   class_id_UNI  on class(id);


方法二

alter table 表名 add unique 索引名(列名)

#為class表name 欄位建立唯一鍵

alter table class add unique class_name_UNI(name);


方法三

通過修改欄位屬性或者修改欄位名。來新增或者修改約束型別

alter table class modify 欄位 值型別 unique;

alter table 表名 change 欄位 欄位 值型別 unique

#為 class表的 score 欄位 新增約束型別
alter table class  modify score int unique;
或者
alter table class change score score int unique;


5.3 刪除唯一鍵約束

alter table 表名 drop index 唯一鍵名;

#查看錶的詳細資訊。得到唯一鍵名為 id
show create table class;
#刪除名為id的唯一鍵
alter table class drop index id

6 主鍵約束(primary key)

主鍵約束相當於 唯一約束 + 非空約束 的組合,主鍵約束列不允許重複,也不允許出現空值。

每個表最多隻允許一個主鍵,建立主鍵約束可以在列級別建立,也可以在表級別建立。

當建立主鍵的約束時,系統預設會在所在的列和列組合上建立對應的唯一索引。


主鍵約束(主鍵索引)與建立唯一性約束的方法相同


6.1 建立表時設定主鍵索引

create  table class2(id int primary key,card_id bigint,name char(20));
 create  table class3(id int,card_id bigint,name char(20),primary key(id));


6.2 通過修改表結構設定主鍵約束

#為class 表的id 欄位建立主鍵
alter table  class add primary key(id);
或者
alter table class modify id int primary key;
或者
alter table class change id id int primary key;


6.3 刪除主鍵約束

alter table 表名 drop primary key;

(1) 當欄位只有主鍵約束,沒有其他約束時,可以直接刪除主鍵

#當欄位沒有其他約束時,可以直接刪除主鍵
alter table class1 drop  primary key;


(2) 當欄位有其他約束時,先刪除其他約束,在刪除主鍵

#先通過修改表字段屬性,刪除自增約束
alter table class modify id int ;
#再刪除id 欄位的主鍵約束
alter table class drop primary key;



7 外來鍵約束

外來鍵約束是用來加強兩個表(主表和從表)的一列或多列資料之間的連線的,可以保證一個或兩個表之間的參照完整性,外來鍵是構建於一個表的兩個欄位或是兩個表的兩個欄位之間的參照關係。

建立外來鍵約束的順序是先定義主表的主鍵,然後定義從表的外來鍵。也就是說只有主表的主鍵才能被從表用來作為外來鍵使用,被約束的從表中的列可以不是主鍵,主表限制了從表更新和插入的操作。

主表和從表關聯的欄位要具有相同的資料型別,字元長度,引數型別

只有當主表中主鍵欄位存在某個數值,從表的才可以新增相應的表記錄

主表刪除時表記錄時,如果該項數值在從表中被使用,則需要先將從表中的佔用刪除,才可以在主表中刪除相應的表記錄


create table 表名(欄位名列表, foreign key(欄位名) references 表名(欄位名)on update cascade on delete cascade)engin=innodb;

foreign key(欄位名):設定從表的外來鍵欄位

references 表名(欄位名) :設定關聯的主表的主鍵欄位

on update cascade : 同步更新,主表字段跟新,從表也相應的更新

on delete cascade: 同步刪除,當主表的記錄刪除,則從表引用該欄位的表記錄也自動刪除

engin=innodb: 設定表的儲存引擎為innodb,如果預設引擎時innodb,可以省略此項



7.1 先建立主表,主鍵

#建立表project,並設定 id 欄位為 主鍵
create  table project(id int  primary key,subject char(30));

#向project 表插入3條記錄
insert into project(id,subject) 
    -> values
    -> (1,'chinese'),
    -> (2,'math'),
    -> (3,'English');



7.2 建立外來鍵

#建立表class,設定id 欄位為主鍵,設定fail 欄位為外來鍵,關聯到project表的id 欄位。並且,同步更新,同步刪除
create table class
    -> (id int primary key,
    -> name char(20),
    -> fail int,
    -> foreign key(fail) references project(id)
    ->  on update cascade 
    -> on delete cascade ); 



7.3 測試從表與主表的關聯

 #插入記錄測試   
insert into  class values (1,'zhangsan',2);
insert into  class values (2,'lisi',2);
insert into  class values (3,'wangwu',3);
insert into  class values (4,'zhaoliu',4); #此條記錄插入失敗


#自動同步測試
#主表將id 欄位,值為2的表記錄更改,將id欄位值變為4,檢視從表的fail 欄位值
update  project  set id=4 where id=2;
 select * from class;
 
 #自動刪除測試
 #主表將 id欄位為 4 的表記錄都刪除,檢視從表的表記錄情況
 delete from project where id=4;
 select * from class;


7.4 通過修改表結構來設定外來鍵

alter table 外來鍵表名 add [constraint 外來鍵名] foreign key(外來鍵欄位) references 主鍵表(主鍵表主鍵欄位);



7.5 刪除外來鍵

alter table 表名 drop foreign key 外來鍵名

alter table 表名 drop index 索引名

在建立外來鍵約束的同時,也會建立外來鍵索引。想要完全刪除外來鍵,需要兩個一起刪除


(1) 先檢視外來鍵名

#檢視建表的詳細資訊
show create table class1;
#得到外來鍵名為 class1_ibfk_1


(2)刪除外來鍵約束

#刪除外來鍵  class1_ibfk_1 
alter table class1 drop foreign key class1_ibfk_1;
#檢視class1表的詳細資訊
show create table class1;


(3) 刪除外來鍵索引

#刪除外來鍵索引 id
alter table class1 drop index id;
#查看錶class1 的詳細資訊
show create table class1;



8 預設約束(default)

若在表中定義了預設值約束,使用者在插入新的資料行時,如果該行沒有指定資料,那麼系統將預設值賦給該列,如果我們不設定預設值,系統預設為NULL。

設定預設值的欄位,預設值的型別必須和欄位的值型別一樣

8.1 建立表時候設定預設約束

create table 表名(欄位名 值型別 default 預設值);

#建立表class,並設定欄位 address的預設值為 'not known'
create table class(id int ,name char(20) ,address  char(40) default 'not known');

#插入表記錄,並且不給address 欄位賦值
insert into class(id,name) values(1,'zhangsan');

select * from class;


8.2 通過修改 表字段來設定預設值

alter table 表名 modify 欄位 值型別 default 預設值;

alter table 表名 change 欄位 欄位 值型別 default 預設值;

這兩條命令同時也可以刪除預設值。只要將default 後面的預設值設定為NULL即可

#將class 表的name 欄位設定預設值為'not known'
alter table class modify name char(40) default 'not known';
#將class 表的 id 欄位設定預設值為0
 alter table class change id  id int  default '0';



9 自增約束(auto_increment)

自增約束(AUTO_INCREMENT)可以約束任何一個欄位,該欄位不一定是PRIMARY KEY欄位,也就是說自增的欄位並不等於主鍵欄位。

但是PRIMARY_KEY約束的主鍵欄位,一定是自增欄位,即PRIMARY_KEY 要與AUTO_INCREMENT一起作用於同一個欄位。

當插入第一條記錄時,自增欄位沒有給定一個具體值,可以寫成DEFAULT/NULL,那麼以後插入欄位的時候,該自增欄位就是從1開始,沒插入一條記錄,該自增欄位的值增加1。當插入第一條記錄時,給自增欄位一個具體值,那麼以後插入的記錄在此自增欄位上的值,就在第一條記錄該自增欄位的值的基礎上每次增加1。

自增約束要設定在數值型別為整形的欄位上,且欄位時主鍵,外來鍵,唯一鍵的一種


9.1 在建立按表的時候,設定自增長

create table 表名(欄位 數值型別 主鍵或外來鍵或者唯一鍵 auto_increment);

#設定class 表id 欄位為整型,主鍵,且自增長
create table class(id int  primary key auto_increment , name char(20));

#插入記錄測試
insert into  class(name) values('zhangsan');
insert into  class(name) values('lisi');


9.2 修改表結構,設定欄位值自增長

alter table 表名 modify 欄位 int auto_increment;

alter table 表名 change 欄位 欄位 int auto_increment;

此命令也可以刪除欄位值自增長。當欄位值存在自增長設定時,使用這兩條命令時,不跟上auto_increment,即表示刪除 欄位的自增長設定

#設定 class表的id 欄位自增長(id 欄位必須已經設定了主鍵或者外來鍵,或者唯一鍵,並且時整型)
alter table class modify id int auto_increment;
或者
alter table class change id id int auto_incremnet;



二: 索引

1 資料庫索引概念

1.1 概念

  1. 索引時一個排序的列表,在這個列表中的值儲存著索引的值和包含這個值的資料所在行的實體地址
  2. 使用索引後,可以不用掃描全表來定位某行資料,而是先通過索引表找到改行資料對飲的實體地址,然後訪問相應的數,加快資料庫的查詢速度
  3. 索引可以類比為書籍的目錄,可以根據目錄中的頁碼來快速找到所需的內容。
  4. 索引時表中一列過著若干列值排序的方法
  5. 建立索引的目的是加快表記錄的查詢或排序

1.2 索引項和索引值

  • 索引項是資料庫裡面的table 中的欄位;
  • 索引值是欄位裡面儲存的資料(值)

1.3 索引的作用與副作用

  • 索引的作用
    • ​ 索引主要有兩個作用,加快搜索速度和排序
  • 索引的副作用
    • 索引需要佔用額外的磁碟空間
    • 在插入和修改資料時,需要花費更多的時間,因為索引也要隨之改動

1.4 建立索引的原則依據

索引隨可以提升資料庫查詢的速度,但並不是任何情況下都適合建立索引。因為索引本身會消耗系統資源,在有索引的情況下,資料庫會先進行索引查詢,然後定位到具體的資料行,如果索引使用不當,反而會增加資料庫的負擔。

  • 表的主鍵、外來鍵必須有索引。因為主鍵具有唯一性,外來鍵關聯的是子表的主鍵,查詢時可以快速定位。
  • 記錄數超過300行的表應該有索引。如果沒有索引,需要把表遍歷一遍,會嚴重影響資料庫的效能。
  • 經常與其他表進行連線的表,在連線欄位上應該建立索引。
  • 唯一性太差的欄位不適合建立索引。
  • 更新太頻繁地欄位不適合建立索引。
  • 經常出現在 where 子句中的欄位,特別是大表的欄位,應該建立索引。
  • 在經常進行 GROUP BY、OPDER BY 的欄位上建立索引
  • 索引應該建在選擇性高的欄位上。
  • 索引應該建在小欄位上,對於大的文字欄位甚至超長欄位,不要建索引。
  • 在讀比較多的表,適合建立索引。

1.5 資料庫查詢的過程

  1. 在有索引的情況下,資料庫會先進行索引查詢,然後定位到具體的資料行
  2. 沒有有索引的情況下掃描全表來定位某行的資料


2 索引的分類

索引有普通索引,唯一索引,主鍵索引,外來鍵索引,組合索引,全文索引。

唯一鍵約束就是唯一索引(unique key),

主鍵索引(primary key),外來鍵索引(foreign key) ,在建立主鍵約束,外來鍵約束時候,會自動建立




3 普通索引

普通索引時最基本的索引型別,沒有唯一性之類的限制


方法一: 直接建立索引

create index 索引名 on 表名(列名(length));

(列名(length)): length 是可選項。如果忽略length 值,則使用整個列的值作為索引。如果指定,使用列的前 length 個字元來建立索引,有利於減小索引檔案的大小。在不損失精度的情況下,長度越短越好。

索引名:普通索引的索引名建議以 " _index" 為結尾


方法二: 修改表的方式建立

alter table 表名 add index 索引名(列名);


方法三:建立表的時候指定索引

create table 表名(欄位名 資料型別 ......, index 索引名(列名);



3.1 建立普通索引

#建立表的時候,為score 欄位設定索引
create table class(id int, name char(30),score int ,index class_score_index(score));

#修改表的方式,為name 欄位建立索引
 alter table class add index class_name_index(name);
 
 #直接為class表id 欄位建立索引
 create index class_id_index on class(id);


3.2 檢視索引

show index form 表名;

#查看錶class 的索引
show index from class \G



4 組合索引

組合索引(單列索引與多列索引):可以是單列上建立的索引,也可以在多列上建立的索引。需要滿足最左原則。因為select 語句的where 條件是依次從左向右執行的,所以在使用select語句查詢時,where 條件的使用欄位順序必須和組合索引中的排序一致,否則索引不會生效


create table 表名 (欄位名 屬主型別 ......, index 索引名(列名1,列名2...));


#建立class 表,並將 id,name,score 欄位設定為組合索引
create table class(id int,name char(20),score int, index class_MUL_index(id,name,score));



5 全文索引

全文索引(fulltext) 適合在模糊查詢時候使用,可以用於一篇文章中檢查文字資訊。

在mysql 5.6 之前只能用於MyISAM 引擎,5.6 之後,可以用於InnoDB 引擎。

全文索引可以子啊char,varchar 後者text 型別的列上建立。

每個表只允許有一個全文索引


方法一:直接建立全文索引

create fulltext index 索引名 on 表名(列名);


方法二: 建立表時候指定索引

create table 表名(欄位名 資料型別 ..... ,fulltext 索引名(欄位名));


方法三: 修改表方式建立

alter table 表名 add fulltext 索引名 on 表名(欄位名);


5.1 建立全文索引

 create table class(id int,name char(30),
    ->  tel bigint ,
    -> address varchar(50),
    -> info varchar(100),
    -> fulltext textindex(info));


5.2 模糊查詢匹配

select * from 表名 where match(欄位名) against('匹配內容');

 #插入三條表記錄
 insert into class values (1,'zhangsan',1010110,'china','this is vip'),
    -> (2,'lisi',1010110,'china','this is super vip'),
    -> (3,'wangwu',1010110,'china','this is  vvip');

#在clss 表的info 欄位,查詢匹配 ‘vip’ 的表記錄
select * from class where match(info) against('vip');



6 檢視索引

show index from 表名;

show key from 表名;


 show index from class \G

欄位 含義
Table :表的名稱

Non_unique :如果索引不能包括重複詞,則為 0;如果可以,則為 1

Key_name: 索引的名稱

Seq_in_index: 索引中的列序號,從 1 開始

Column_name: 列名稱

Collation :列以什麼方式儲存在索引中。在 MySQL 中,有值‘A’(升序)或 NULL(無分類)

Cardinality :索引中唯一值數目的估計值

Sub_part: 如果列只是被部分地編入索引,則為被編入索引的字元的數目。如果整列被編入索引,為 NULL

Packed: 指示關鍵字如何被壓縮。如果沒有被壓縮,則為 NULL

Null :如果列含有 NULL,則含有 YES。如果沒有,則該列含有 NO

Index_type: 用過的索引方法(BTREE, FULLTEXT, HASH, RTREE)

Comment: 備註




7 刪除索引

直接刪除索引

drop index 索引名 on 表名;


修改表的方式刪除索引

alter table 表名 drop index 索引名;


刪除主鍵索引

alter table 表名 drop primary key



#查看錶的詳細資訊,獲取索引名
show create table class \G

#刪除索引
drop index textindex on class;