2-16 MySQL字段約束-索引-外鍵

 

一:字段修飾符 mysql

1:null和not null修飾符 算法

咱們經過這個例子來看看 sql

mysql> create table worker(id int not null,name varchar(8) not null,pass varchar(20) not null); 數據庫

mysql> insert into worker values(1,'HA','123456'); 安全

mysql> insert into worker values(1,'LB',null); 服務器

ERROR 1048 (23000): Column 'pass' cannot be null  不能爲null 併發

mysql> insert into worker values(2,'HPC',''); 高併發

注:NOT NULL 的字段是不能插入「NULL」的,只能插入「空值」。 性能

咱們可能有這些疑問<null和not null區別> 測試

一、字段類型是not null,爲何能夠插入空值

二、爲何not null的效率比null高

三、判斷字段不爲空的時候,到底要  select * from table where column <> '' 仍是要用 select * from table where column is not null 呢。

「空值」 和 「NULL」有什麼不同?

一、空值是不佔用空間的

二、mysql中的NULL實際上是佔用空間的,下面是來自於MYSQL官方的解釋

「NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.」

#「空列須要行中的額外空間來記錄其值是否爲空。對於MyISAM表,每一個NULL列須要一個額外的位,四捨五入到最接近的字節。

好比:一個杯子,空值''表明杯子是真空的,NULL表明杯子中裝滿了空氣,雖然杯子看起來都是空的,可是裏面是有空氣的。

對於問題2,爲何not null的效率比null高?

NULL 其實並非空值,而是要佔用空間,因此mysql在進行比較的時候,NULL 會參與字段比較,因此對效率有一部分影響。

並且索引時不會存儲NULL值的,因此若是索引的字段能夠爲NULL,索引的效率會降低不少。

-Mysql難以優化引用可空列查詢,它會使索引、索引統計和值更加複雜。可空列須要更多的存儲空間,還須要mysql內部進行特殊處理。可空列被索引後,每條記錄都須要一個額外的字節,還能致使MyISAM中固定大小的索引變成可變大小的索引--------這也是《高性能mysql第二版》介紹的解讀:「可空列須要更多的存儲空間」:須要一個額外字節做爲判斷是否爲NULL的標誌位「須要mysql內部進行特殊處理」

因此使用not null 比null效率高

對於問題3. 判斷字段不爲空的時候,到底要  select * from table where column <> '' 仍是要用 select * from table where column is not null咱們舉例看看

mysql> create table test(col1 varchar(10) not null, col2 varchar(10) null)ENGINE=MyISAM;

mysql> insert into test values('',null);

mysql> insert into test values('1','2');

mysql> insert into test values('','1');

wps8AFA.tmp

下面我分別用這兩條語句查詢看看

wps8AFB.tmp

wps8AFC.tmp

爲空表示不佔空間,null佔用空間

2:default 設定字段的默認值

爲字段指定默認的值

mysql> create table test2(name varchar(8) not null,dept varchar(25) default 'SOS');

mysql> insert into test2 (name) values ('kko');

wps8AFD.tmp

總結 :

若是字段沒有設定default ,mysql依據這個字段是null仍是not null,若是爲能夠爲null,則爲null。若是不能夠爲null,報錯。。

若是時間字段,默認爲當前時間 ,插入0時,默認爲當前時間。

若是是enum 類型,默認爲第一個元素。

3:auto_increment字段約束

自動增加

只能修飾 int字段。 代表mysql應該自動爲該字段生成一個惟一沒有用過的數(每次在最大ID值的基礎上加1。特例:若是目前最大ID是34,而後刪除34,新添加的會是35.)。對於主鍵,這是很是 有用的。 能夠爲每條記錄建立一個唯一的標識符

mysql> create table items ( id int not null auto_increment primary key , label varchar(20) not null);

mysql>  insert into items (label) values ('aaba');

mysql>  insert into items values (9,'aaba');

再插入一條id將爲多少

mysql>  insert into items (label) values ('abc');

wps8AFE.tmp

Id爲10

mysql>  insert into items values (9,'adl');

ERROR 1062 (23000): Duplicate entry '9' for key 'PRIMARY'

insert into items (label) values ('abcs');       IDmax =11  max=11

delete from items where label='abcs';       IDmax=10 max=11

insert into items (label) values ('abcsw');     Idmax=11 max=12

主鍵約束惟一

二:清除表中的記錄

清空表中全部記錄

方法一:delete 不加where條件,清空全部表記錄。可是delete不會清零auto_increment 值

mysql> delete from items;

wps8AFF.tmp

mysql> insert into items (label) values ("aaaa");

wps8B0F.tmp

方法二:刪除表中全部記錄,清auto_increment 值。

truncate

做用: 刪除表的全部記錄,並清零auto_increment 值。新插入的記錄從1開始。

語法: truncate  table  name;

mysql> truncate table items;

wps8B10.tmp

mysql> insert into items values(null,'abv');

wps8B11.tmp

mysql> insert into items(label)values('hkuyb');

wps8B12.tmp

三:索引

索引是一種特殊的文件(InnoDB數據表上的索引是表空間的一個組成部分),它們包含着對數據表裏全部記錄的引用指針。更通俗的說,數據庫索引比如是一本書前面的目錄,能加快數據庫的查詢速度。

優勢:爲了加快搜索速度,減小查詢時間 。

缺點:

1 索引是以文件存儲的。若是索引過多,佔磁盤空間較大。並且他影響: insert ,update ,delete 執行時間。

2索引中數據必須與數據表數據同步:若是索引過多,當表中數據更新的時候後,索引也要同步更新,這就下降了效率。

索引的類型

一、普通索引

二、惟一性索引

三、主鍵索引(主索引)

四、複合索引

普通索引

最基本的索引,不具有惟一性,就是加快查詢速度

建立普通索引:

方法一:建立表時添加索引

create table 表名(

               列定義

               index 索引名稱 (字段)

               index 索引名稱 (字段));

 

注:可使用key,也可使用index 。index 索引名稱 (字段)  ,索引名稱,能夠加也能夠不加,不加使用字段名做爲索引名。。

mysql> create table demo( id int(4), name varchar(20), pwd varchar(20), index(pwd) );

注意:index和 key 是相同的

mysql> create table demo1( id int(4), name varchar(20), pwd varchar(20), key(pwd) );

mysql> create table demo2( id int(4), name varchar(20), pwd varchar(20), key index_pwd(pwd) );  #加上名稱

方法二: 當表建立完成後,使用alter爲表添加索引:

alter table 表名 add index 索引名稱 (字段1,字段2.....);

查看索引

wps8B13.tmp

注:若是Key是MUL, 那麼該列的值能夠重複, 該列是一個非惟一索引的前導列(第一列)或者是一個惟一性索引的組成部分可是能夠含有空值NULL。就是表示是一個普通索引。

咱們先刪除索引

mysql> alter table demo drop key pwd; 注意此處的pwd指的是索引的名稱,而不是表中pwd的那個字段

再用alter添加

mysql> alter table demo add key(pwd);

惟一索引

與普通索引基本相同,但有一個區別:索引列的全部值都只能出現一次,即必須惟一,用來約束內容,字段值只能出現一次。應該加惟一索引。惟一性容許有NULL值<容許爲空>。

建立惟一索引:

方法一:建立表時加惟一索引

create table 表名(

列定義:

unique key 索引名 (字段);

)

注意:經常使用在值不能重複的字段上,好比說用戶名,電話號碼,身份證號。

mysql> create table demo3(id int(4) auto_increment primary key, uName varchar(20), uPwd varchar(20), unique  index  (uName));

wps8B14.tmp

方法二:修改表時加惟一索引

alter table 表名 add unique 索引名 (字段);

mysql> alter table demo3 drop key uName;

mysql> alter table demo3 add unique(uName);

主鍵索引

查詢數據庫,按主鍵查詢是最快的,每一個表只能有一個主鍵列,能夠有多個普通索引列。主鍵列要求列的全部內容必須惟一,而索引列不要求內容必須惟一,不容許爲空

建立主鍵索引

方法一:建立表建立主鍵索引

mysql> create table demo4 (id int(4) not null auto_increment primary key,name varchar(4) not null );

mysql> create table demo5( id int(4) not null auto_increment, name varchar(20) default null,primary key(id));

wps8B15.tmp

mysql> show create table demo5;

show index from demo5 \G

wps8B16.tmp

方法二:建立表後添加<不推薦>

先刪除測試

wps8B27.tmp

刪除遇到這種狀況是auto_increment的緣由

mysql> alter table demo5 change id id int(4) not null;

mysql> alter table demo5 drop primary key;

再添加

mysql> alter table demo5 change id id int(4) not null primary key auto_increment;

總結:主鍵索引,惟一性索引區別:主鍵索引不能有NULL,惟一性索引能夠有空值

複合索引

索引能夠包含一個、兩個或更多個列。兩個或更多個列上的索引被稱做複合索引

例: 建立一個表存放服務器容許或拒絕的IP和port,要記錄中IP和port要惟一。

mysql> create table firewall ( host varchar(15) not null ,port smallint(4) not null ,access enum('deny','allow') not null, primary key (host,port));

wps8B28.tmp

mysql> insert into firewall values('10.96.52.46',22,'deny');

mysql> insert into firewall values('10.96.52.46',21,'allow');

mysql> insert into firewall values('10.96.52.46',21,'allow');

ERROR 1062 (23000): Duplicate entry '10.96.52.46-21' for key 'PRIMARY'

插入同樣就報錯,惟一

總結:

建表的時候若是加各類索引,順序以下:

create table 表名(字段定義,PRIMARYKEY  (`bId`),UNIQUE KEY `bi` (`bImg`),KEY `bn` (`bName`),KEY `ba` (`author`))

全文索引 (FULLTEXT INDEX)

全文索引(也稱全文檢索)是目前搜索引擎使用的一種關鍵技術。它可以利用「分詞技術「等多種算法智能分析出文本文字中關鍵字詞的頻率及重要性,而後按照必定的算法規則智能地篩選出咱們想要的搜索結果

mysql 在數據量較大的狀況下,高併發鏈接的狀況下。

select 語句  where bName like '%網%'

使用% _ 通配符,不經過索引,直接全表掃描。

ABSUWU  LIKE ‘%U_U’

數據庫壓力大。

mysql的解決方案:全文索引:3.2開始支持全文索引。沒法正確支持中文。

全文索引只能用在 varchar text

建立全文索引:

方法一:建立表時建立

create table 表名(

列定義,

fulltext key 索引名 (字段);

方法二:修改表時添加

alter table 表名 add fulltext 索引名 (字段);

ALTER TABLE `books` ADD FULLTEXT  索引名 (`author` )

強烈注意:MySQL自帶的全文索引只能用於數據庫引擎爲MyISAM的數據表,若是是其餘數據引擎,則全文索引不會生效

MySQL自帶的全文索引只能對英文進行全文檢索,目前沒法對中文進行全文檢索。

通常交給第三方軟件進行全文索引

http://sphinxsearch.com/

索引設計原則:

索引並不是越多越好

數據量不大不須要創建索引

列中的值變化很少不須要創建索引 row id

常常排序(order by)和分組(group by)的列須要創建索引

惟一性約束對應使用惟一性索引

四:外鍵約束

什麼是外鍵約束:

foreign key就是表與表之間的某種約定的關係,因爲這種關係的存在,咱們可以讓表與表之間的數據,更加的完整,關連性更強。

關於完整性,關連性咱們舉個例子

有二張表,一張是用戶表,一張是訂單表:

1》若是我刪除了用戶表裏的用戶,那麼訂單表裏面根這個用戶有關的數據,就成了無頭數據了,不完整了。

2》若是我在訂單表裏面,隨便插入了一條數據,這個訂單在用戶表裏面,沒有與之對應的用戶。這樣數據也不完整了。

若是有外鍵的話,就方便多了,能夠不讓用戶刪除數據,或者刪除用戶的話,經過外鍵一樣刪除訂單表裏面的數據,這樣也能讓數據完整。

建立外鍵約束:

外鍵: 每次插入或更新時,都會檢查數據的完整性。

方法一:經過create table建立外鍵

語法:

create table 數據表名稱(

...,

[CONSTRAINT [約束名稱]] FOREIGN KEY [外鍵字段]
    REFERENCES [外鍵表名](外鍵字段,外鍵字段2…..)
    [ON DELETE  C
ASCADE ]
    [ON UPDATE CASCADE  ]

)

關於參數的解釋:

RESTRICT: 拒絕對父表的刪除或更新操做。

CASCADE: 從父表刪除或更新且自動刪除或更新子表中匹配的行。ON DELETE CASCADE和ON UPDATE CASCADE均可用

注意:on update cascade是級聯更新的意思,on delete cascade是級聯刪除的意思,意思就是說當你更新或刪除主鍵表,那外鍵表也會跟隨一塊兒更新或刪除。

精簡化後的語法:

語法:foreign key 當前表的字段  references  外部表名  (關聯的字段)  type=innodb

注:建立成功,必須知足如下4個條件:

一、確保參照的表和字段存在。

二、組成外鍵的字段被索引。

三、必須使用type指定存儲引擎爲:innodb.

四、外鍵字段和關聯字段,數據類型必須一致。

例子:咱們建立一個數據庫,包含用戶信息表和訂單表

mysql> create database market;

mysql> create table `user`(id int(11) not null auto_increment, name varchar(50) not null default '', sex int(1) not null default '0', primary key(id))ENGINE=innodb;

#建立時,若是表名是sql關鍵字,使用時,須要使用反引號``

mysql> create table `order`(o_id int(11) auto_increment, u_id int(11) default '0', username varchar(50), money int(11), primary key(o_id), index(u_id), foreign key order_f_key(u_id) references user(id) on delete cascade on update cascade) ENGINE=innodb;

注:

1:on delete cascade  on update cascade 添加級聯刪除和更新:

2: :確保參照的表user中id字段存在。 組成外鍵的字段u_id被索引。 必須使用type指定存儲引擎爲:innodb。

外鍵字段和關聯字段,數據類型必須一致。

插入測試數據

mysql> insert into user(name,sex)values('HA',1),('LB',2),('HPC',1);

mysql> insert into `order` (u_id,username,money)values(1,'HA',234),(2,'LB',146),(3,'HPC',256);

wps8B29.tmp

wps8B2A.tmp

測試級聯刪除:

mysql> delete from user where id=1; 刪除user表中id爲1的數據

再查看order表

wps8B2B.tmp

測試級聯更新:

更新前數據狀態

wps8B2C.tmp

mysql> update user set id=6 where id=2;

wps8B2D.tmp

測試數據完整性

wps8B2E.tmp

外鍵約束,order表受user表的約束

在order裏面插入一條數據u_id爲5用戶,在user表裏面根本沒有,因此插入不進去

mysql> insert into user values(5,'Find',1);

mysql> insert into `order` (u_id,username,money)values(5,'Find',346);

wps8B3F.tmp

方法二:經過alter table 建立外鍵和級聯更新,級聯刪除

語法:

alter table 數據表名稱 add

[constraint [約束名稱] ]  foreign key (外鍵字段,..) references 數據表(參照字段,...)

[on update cascade|set null|no action]

[on delete cascade|set null|no action]

)

mysql> create table order1(o_id int(11) auto_increment, u_id int(11) default '0', username varchar(50), money int(11), primary key(o_id), index(u_id))type=innodb;

mysql> alter table order1 add foreign key(u_id) references user(id) on delete cascade on update cascade,type=innodb;

mysql> alter table order1 add constraint `bk`foreign key(u_id) references user(id) on delete cascade on update cascade,type=innodb;  指定外鍵名稱

必定要記得帶上innodb

mysql> show create table order1;

wps8B40.tmp

刪除外鍵:

語法

alter table 數據表名稱 drop foreign key 約束(外鍵)名稱

mysql> alter table order1 drop foreign key order1_ibfk_1;

mysql> show create table order1;

wps8B41.tmp

五:視圖

什麼是視圖

視圖就是一個存在於數據庫中的虛擬表。

視圖自己沒有數據,只是經過執行相應的select語句完成得到相應的數據。

咱們在怎樣的場景使用它,爲何使用視圖

若是某個查詢結果出現的很是頻繁,也就是,要常常拿這個查詢結果來作子查詢這種

視圖可以簡化用戶的操做

視圖機制用戶能夠將注意力集中在所關心的數據上。若是這些數據不是直接來自基本表,則能夠經過定義視圖,使數據庫看起來結構簡單、清晰,而且能夠簡化用戶的數據查詢操做

視圖是用戶能以不一樣的角度看待一樣的數據。

對於固定的一些基本表,咱們能夠給不一樣的用戶創建不一樣的視圖,這樣不一樣的用戶就能夠看到本身須要的信息了。

視圖對重構數據庫提供了必定程度的邏輯性。

好比原來的A表被分割成了B表和C表,咱們仍然能夠在B表和C表的基礎上構建一個視圖A,而使用該數據表的程序能夠不變。

視圖可以對機密數據提供安全保護

好比說,每門課的成績都構成了一個基本表,可是對於每一個同窗只能夠查看本身這門課的成績,所以能夠爲每一個同窗創建一個視圖,隱藏其餘同窗的數據,只顯示該同窗本身的

適當的利用視圖能夠更加清晰的表達查詢數據。

有時用現有的視圖進行查詢能夠極大的減少查詢語句的複雜程度。

建立視圖

語法:create view視圖名稱(即虛擬的表名) as select 語句。

咱們在book數據庫中操做

mysql>  create view bc as select b.bName ,b.price ,c.bTypeName from books as b left join category as c  on b.bTypeId=c.bTypeId ;

能夠按照普通表去訪問。

另外視圖表中的數據和原數據表中數據是同步的。

查看視圖建立信息:

mysql> show create view bc \G

wps8B42.tmp 

查詢視圖中的數據

wps8B43.tmp

更新或修改視圖

語法:

alter view視圖名稱(即虛擬的表名) as select 語句。

update view視圖名稱(即虛擬的表名)set

mysql> alter view bc as select b.bName ,b.publishing ,c.bTypeId from books as b left join category as c  on b.bTypeId=c.bTypeId ;

wps8B44.tmp

更新

mysql> update bc set bName='HA' where price=34;

wps8B45.tmp

刪除視圖

drop view 視圖名。

mysql> drop view bc;

相關文章
相關標籤/搜索