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

高版本導出報錯問題,是因爲高版本對導出文件優化了權限設置,
show variables like '%secure%'; 查看權限是NULL就表明禁止導出
在配置文件my.cnf [mysqld]下加secure_file_priv=指定導出目錄
 
 
本節所講內容:
1.  字段修飾符
2.  清空表記錄
3.  索引
4.  外鍵
5.     視圖

一:字段修飾符 (約束)
1 :null和not null修飾符
 
咱們經過這個例子來看看
  1. mysql> create table worker(id int not null,name varchar(8) not null,pass varchar(20) not null);
  2. 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」有什麼不同?
1 、空值是不佔用空間的
2 、mysql中的NULL實際上是佔用空間的,下面是來自於MYSQL官方的解釋
 
「NULL columns require additional space in therow to record whether their values are NULL. For MyISAM tables, each NULLcolumn 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咱們舉例看看
  1. mysql> create table test(col1 varchar(10) not null, col2 varchar(10) null)ENGINE=MyISAM;
  2. mysql> insert into test values('',null);
  3. mysql> insert into test values('1','2');
  4. mysql> insert into test values('','1');


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


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

2 :default設定字段的默認值


爲字段指定默認的值
  1. mysql> create table test2(name varchar(8) not null,dept varchar(25) default 'SOS');
  2. mysql> insert into test2 (name) values ('kko');


總結 :
若是字段沒有設定default ,mysql依據這個字段是null仍是not null,若是爲能夠爲null,則爲null。若是不能夠爲null,報錯。。
若是時間字段,默認爲當前時間 ,插入0時,默認爲當前時間。
若是是enum 類型,默認爲第一個元素。

3 :auto_increment字段約束

自動增加
只能修飾 int字段。 代表mysql應該自動爲該字段生成一個惟一沒有用過的數(每次在最大ID值的基礎上加1。特例:若是目前最大ID是34,而後刪除34,新添加的會是35.)。對於主鍵,這是很是 有用的。 能夠爲每條記錄建立一個唯一的標識符
  1. mysql> create table items ( id int not null auto_increment primary key , label varchar(20) not null);
  2. mysql>  insert into items (label) values ('aaba');
  3. mysql>  insert into items values (9,'aaba');

再插入一條id將爲多少
  1. mysql>  insert into items (label) values ('abc');


Id 爲10
 
  1. mysql>  insert into items values (9,'adl');
ERROR1062 (23000): Duplicate entry '9' for key 'PRIMARY'
 
insertinto items (label) values ('abcs');       IDmax =11 max=11
deletefrom items where label='abcs';       IDmax=10max=11
insertinto items (label) values ('abcsw');     Idmax=11max=12
 
主鍵約束惟一
二:清除表中的記錄
清空表中全部記錄
方法一:delete 不加where條件,清空全部表記錄。可是delete不會清零auto_increment 值
 
  1. mysql> delete from items;


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


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

truncate
做用: 刪除表的全部記錄,並清零auto_increment 值。新插入的記錄從1開始。
語法: truncate  table name;
  1. mysql> truncate table items;

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



  1. mysql> insert into items(label)values('hkuyb');
 
三:索引
 
索引是一種特殊的文件(InnoDB數據表上的索引是表空間的一個組成部分),它們包含着對數據表裏全部記錄的引用指針。更通俗的說,數據庫索引比如是一本書前面的目錄,能加快數據庫的查詢速度。
點:爲了加快搜索速度,減小查詢時間。
缺點:
索引是以文件存儲的。若是索引過多,佔磁盤空間較大。並且他影響: insert ,update ,delete 執行時間。
2 索引中數據必須與數據表數據同步:若是索引過多,當表中數據更新的時候後,索引也要同步更新,這就下降了效率。

索引的類型
1 、普通索引
2 、惟一性索引
3 、主鍵索引(主索引)
4 、複合索引
普通索引
最基本的索引,不具有惟一性,就是加快查詢速度
建立普通索引:
方法一:建立表時添加索引
createtable  表名(
        列定義
       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爲表添加索引:
altertable  表名 addindex 索引名稱 (字段1,字段2.....);

查看索引


注:若是Key是MUL, 就是通常性索引,該列的值能夠重複, 該列是一個非惟一索引的前導列(第一列)或者是一個惟一性索引的組成部分可是能夠含有空值NULL。就是表示是一個普通索引。
咱們先刪除索引
mysql>alter table demo drop key pwd;  注意此處的pwd指的是索引的名稱,而不是表中pwd的那個字段
再用alter添加
mysql>alter table demo add key(pwd);
 
惟一索引
與普通索引基本相同,但有一個區別:索引列的全部值都只能出現一次,即必須惟一,用來約束內容,字段值只能出現一次。應該加惟一索引。惟一性容許有NULL值<容許爲空>。
建立惟一索引:
方法一:建立表時加惟一索引
createtable  表名(
        列定義:
       unique key  索引名 (字段);
)
注意:經常使用在值不能重複的字段上,好比說用戶名,電話號碼,身份證號。

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

方法二:修改表時加惟一索引
altertable  表名 addunique 索引名 (字段);
  1. mysql> alter table demo3 drop key uName;
  2. mysql> alter table demo3 add unique(uName);

主鍵索引
查詢數據庫,按主鍵查詢是最快的,每一個表只能有一個主鍵列,能夠有多個普通索引列。主鍵列要求列的全部內容必須惟一,而索引列不要求內容必須惟一,不容許爲空
建立主鍵索引
方法一:建立表建立主鍵索引
  1. mysql> create table demo4 (id int(4) not null auto_increment primary key,name varchar(4) not null );
  2. mysql> create table demo5( id int(4) not null auto_increment, name varchar(20) default null,primary key(id));

  1. mysql> show create table demo5;
  2. show index from demo5 \G


方法二:建立表後添加 < 不推薦> 若是生產的數據沒法保證惟一,建立主鍵報錯
再添加

先刪除測試

刪除遇到這種狀況是auto_increment的緣由
  1. mysql> alter table demo5 change id id int(4) not null; 先取消自增加
  2. mysql> alter table demo5 drop primary key;  再刪除主鍵
  3. mysql> alter table demo5 change id id int(4) not null primary key auto_increment;

總結:主鍵索引,惟一性索引區別:主鍵索引不能有NULL,惟一性索引能夠有空值
複合索引
索引能夠包含一個、兩個或更多個列。兩個或更多個列上的索引被稱做複合索引
例: 建立一個表存放服務器容許或拒絕的IP和port,要記錄中IP和port要惟一。

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

  1. mysql> insert into firewall values('10.96.52.46',22,'deny');
  2. mysql> insert into firewall values('10.96.52.46',21,'allow');
  3. mysql> insert into firewall values('10.96.52.46',21,'allow');
  4. 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開始支持全文索引。沒法正確支持中文。
從MySQL 5.7.6開始 MySQL內置了ngram全文檢索插件,用來支持中文分詞
你的表當前默認的存儲引擎:
mysql> show create table  表名;
 
全文索引只能用在 varchar text
建立全文索引:
方法一:建立表時建立
create table  表名(
        列定義,
       fulltext key  索引名 (字段);
方法二:修改表時添加
alter table  表名 add fulltext 索引名 (字段);
       ALTER TABLE`books` ADD FULLTEXT  [ 索引名](`author` )
強烈注意 :MySQL自帶的全文索引只能用於數據庫引擎爲MyISAM的數據表,若是是其餘數據引擎,則全文索引不會生效
通常交給第三方軟件進行全文索引
http://sphinxsearch.com/
 
索引設計原則:
一、  索引並不是越多越好
二、  數據量不大不須要創建索引
三、  列中的值變化很少不須要創建索引 row id
四、  常常排序(order by 字段)和分組(group by 字段)的列須要創建索引
selecta.bTypeId,(select b.bTypeName from category b where a.bTypeId = b.bTypeId)bn,count(*) from books a group by bTypeId;
五、  惟一性約束對應使用惟一性索引
Table (id pri,use,nameindex,pass)


四:外鍵約束


什麼是外鍵約束:
foreignkey 就是表與表之間的某種約定的關係,因爲這種關係的存在,咱們可以讓表與表之間的數據,更加的完整,關連性更強。
關於完整性,關連性咱們舉個例子
有二張表,一張是用戶表,一張是訂單表:
1 》若是我刪除了用戶表裏的用戶,那麼訂單表裏面與這個用戶有關的數據,就成了無頭數據了,不完整了。
2 》若是我在訂單表裏面,隨便插入了一條數據,這個訂單在用戶表裏面,沒有與之對應的用戶。這樣數據也不完整了。
若是有外鍵的話,就方便多了,能夠不讓用戶刪除數據,或者刪除用戶的話,經過外鍵一樣刪除訂單表裏面的數據,這樣也能讓數據完整。

建立外鍵約束:
外鍵: 每次插入或更新時,都會檢查數據的完整性。
方法一:經過createtable建立外鍵
語法:
create table  數據表名稱(
...,
[CONSTRAINT [ 約束名稱]] FOREIGN KEY [外鍵字段] 
    REFERENCES [外鍵表名](外鍵字段,外鍵字段2…..)
    [ON DELETE  C
AS CADE ]
    [ON UPDATE CASCADE  ]
)
關於參數的解釋:
RESTRICT: 拒絕對父表的刪除或更新操做。
CASCADE: 從父表刪除或更新且自動刪除或更新子表中匹配的行。ON DELETE CASCADE和ON UPDATE CASCADE均可用
注意:on update cascade是級聯更新的意思 ,ondelete cascade是級聯刪除的意思,意思就是說當你更新或刪除主鍵表,那外鍵表也會跟隨一塊兒更新或刪除。
 
精簡化後的語法:
語法:foreign key 當前表的字段  references  外部表名  (關聯的字段)   ENGINE  =innodb
 
注:建立成功,必須知足如下4個條件:
1 、確保參照的表和字段存在。
2 、組成外鍵的字段被索引。
3 、必須使用 ENGINE 指定存儲引擎爲:innodb.
4 、外鍵字段和關聯字段,數據類型必須一致。
例子:咱們建立一個數據庫,包含用戶信息表和訂單表
  1. mysql> create database market;  
  2. mysql> use market;
  3. 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關鍵字,使用時,須要使用反引號``
  1. 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。
外鍵字段和關聯字段,數據類型必須一致。
插入測試數據
  1. mysql> insert into user(name,sex)values('HA',1),('LB',2),('HPC',1);
  2. mysql> insert into `order` (u_id,username,money)values(1,'HA',234),(2,'LB',146),(3,'HPC',256);


 

測試級聯刪除:
mysql>delete from user where id=1;  刪除user表中id爲1的數據

再查看order表


測試級聯更新:

更新前數據狀態

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

 
測試數據完整性
 

外鍵約束,order表受user表的約束
在order裏面插入一條數據u_id爲5用戶,在user表裏面根本沒有,因此插入不進去
  1. mysql> insert into user values(5,'Find',1);
  2. mysql> insert into `order` (u_id,username,money)values(5,'Find',346); 這裏u_id 只能是5

 
方法二:經過altertable 建立外鍵和級聯更新,級聯刪除
語法:
alter table  數據表名稱 add
[constraint [ 約束名稱] ] foreign key (外鍵字段,..) references 數據表(參照字段,...)
[on update cascade|set null|no action]
[on delete cascade|set null|no action]
)
  1. 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)) ENGINE=innodb;
  2. mysql> alter table order1 add foreign key(u_id) references user(id) on delete cascade on update cascade, ENGINE =innodb;
  3. mysql> alter table order1 add constraint `bk`foreign key(u_id) references user(id) on delete cascade on update cascade,type=innodb;  指定外鍵名稱

必定要記得帶上innodb

  1. mysql> show create table order1;

 
刪除外鍵:
語法
alter table  數據表名稱 drop foreign key 約束(外鍵)名稱
  1. mysql> alter table order1 drop foreign key order1_ibfk_1;
  2. mysql> show create table order1;


五:視圖
什麼是視圖
視圖就是一個存在於數據庫中的虛擬表。
視圖自己沒有數據,只是經過執行相應的select語句完成得到相應的數據。
 
咱們在怎樣的場景使用它,爲何使用視圖
若是某個查詢結果出現的很是頻繁,也就是,要常常拿這個查詢結果來作子查詢這種
1.    視圖可以簡化用戶的操做
視圖機制用戶能夠將注意力集中在所關心的數據上。若是這些數據不是直接來自基本表,則能夠經過定義視圖,使數據庫看起來結構簡單、清晰,而且能夠簡化用戶的數據查詢操做
2.    視圖是用戶能以不一樣的角度看待一樣的數據。
對於固定的一些基本表,咱們能夠給不一樣的用戶創建不一樣的視圖,這樣不一樣的用戶就能夠看到本身須要的信息了。
3.    視圖對重構數據庫提供了必定程度的邏輯性。
好比原來的A表被分割成了B表和C表,咱們仍然能夠在B表和C表的基礎上構建一個視圖A,而使用該數據表的程序能夠不變。
4.    視圖可以對機密數據提供安全保護
好比說,每門課的成績都構成了一個基本表,可是對於每一個同窗只能夠查看本身這門課的成績,所以能夠爲每一個同窗創建一個視圖,隱藏其餘同窗的數據,只顯示該同窗本身的
5.    適當的利用視圖能夠更加清晰的表達查詢數據。
有時用現有的視圖進行查詢能夠極大的減少查詢語句的複雜程度。
建立視圖
語法:createview視圖名稱(即虛擬的表名) as select 語句。
咱們在book數據庫中操做
  1. 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 ;

能夠按照普通表去訪問。
另外視圖表中的數據和原數據表中數據是同步的。
查看視圖建立信息:

  1. mysql> show create view bc \G

 
查詢視圖中的數據


更新或修改視圖
語法:
alter view 視圖名稱(即虛擬的表名) as select 語句。
update view 視圖名稱(即虛擬的表名)set

  1. 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 ;

 
  1. 更新
  2. mysql> update bc set bName='HA' where price=34;

刪除視圖
drop view  視圖名。
  1. mysql> drop view bc;

學習mysql 先搞懂它的概念原理,慢慢作實驗理解它真正的用法,而後結合實際爲何要用這個sql寫法。



 

16.png
相關文章
相關標籤/搜索