mysql 完整性約束
阿新 • • 發佈:2018-05-08
用戶 url greate har _id pro PE sca 說明
一 介紹
約束條件與數據類型的寬度一樣,都是可選參數
作用:用於保證數據的完整性和一致性
主要分為:
PRIMARY KEY (PK) 標識該字段為該表的主鍵,可以唯一的標識記錄
FOREIGN KEY (FK) 標識該字段為該表的外鍵
NOT NULL 標識該字段不能為空
UNIQUE KEY (UK) 標識該字段的值是唯一的
AUTO_INCREMENT 標識該字段的值自動增長(整數類型,而且為主鍵)
DEFAULT 為該字段設置默認值
UNSIGNED 無符號
ZEROFILL 使用0填充
說明:
1. 是否允許為空,默認NULL,可設置NOT NULL,字段不允許為空,必須賦值2. 字段是否有默認值,缺省的默認值是NULL,如果插入記錄時不給字段賦值,此字段使用默認值 sex enum(‘male‘,‘female‘) not null default ‘male‘ age int unsigned NOT NULL default 20 必須為正值(無符號) 不允許為空 默認是20 3. 是否是key 主鍵 primary key 外鍵 foreign key 索引 (index,unique...)
二 not null與default
是否可空,null表示空,非字符串
not null - 不可空
null - 可空
默認值,創建列時可以指定默認值,當插入數據時如果未主動設置,則自動添加默認值
create table tb1(
nid int not null defalut 2,
num int not null
)
==================not null==================== mysql> create table t1(id int); #id字段默認可以插入空 mysql> desc t1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ mysql驗證> insert into t1 values(); #可以插入空 mysql> create table t2(id int not null); #設置字段id不為空 mysql> desc t2; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | | NULL | | +-------+---------+------+-----+---------+-------+ mysql> insert into t2 values(); #不能插入空 ERROR 1364 (HY000): Field ‘id‘ doesn‘t have a default value ==================default==================== #設置id字段有默認值後,則無論id字段是null還是not null,都可以插入空,插入空默認填入default指定的默認值 mysql> create table t3(id int default 1); mysql> alter table t3 modify id int not null default 1; ==================綜合練習==================== mysql> create table student( -> name varchar(20) not null, -> age int(3) unsigned not null default 18, -> sex enum(‘male‘,‘female‘) default ‘male‘, -> hobby set(‘play‘,‘study‘,‘read‘,‘music‘) default ‘play,music‘ -> ); mysql> desc student; +-------+------------------------------------+------+-----+------------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------------------------+------+-----+------------+-------+ | name | varchar(20) | NO | | NULL | | | age | int(3) unsigned | NO | | 18 | | | sex | enum(‘male‘,‘female‘) | YES | | male | | | hobby | set(‘play‘,‘study‘,‘read‘,‘music‘) | YES | | play,music | | +-------+------------------------------------+------+-----+------------+-------+ mysql> insert into student(name) values(‘egon‘); mysql> select * from student; +------+-----+------+------------+ | name | age | sex | hobby | +------+-----+------+------------+ | egon | 18 | male | play,music | +------+-----+------+------------+
三 unique
============設置唯一約束 UNIQUE=============== 方法一: create table department1( id int, name varchar(20) unique, comment varchar(100) ); 方法二: create table department2( id int, name varchar(20), comment varchar(100), constraint uk_name unique(name) ); mysql> insert into department1 values(1,‘IT‘,‘技術‘); Query OK, 1 row affected (0.00 sec) mysql> insert into department1 values(1,‘IT‘,‘技術‘); ERROR 1062 (23000): Duplicate entry ‘IT‘ for key ‘name‘View Code
mysql> create table t1(id int not null unique); Query OK, 0 rows affected (0.02 sec) mysql> desc t1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | +-------+---------+------+-----+---------+-------+ 1 row in set (0.00 sec)not null+unique的化學反應
create table service( id int primary key auto_increment, name varchar(20), host varchar(15) not null, port int not null, unique(host,port) #聯合唯一 ); mysql> insert into service values -> (1,‘nginx‘,‘192.168.0.10‘,80), -> (2,‘haproxy‘,‘192.168.0.20‘,80), -> (3,‘mysql‘,‘192.168.0.30‘,3306) -> ; Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> insert into service(name,host,port) values(‘nginx‘,‘192.168.0.10‘,80); ERROR 1062 (23000): Duplicate entry ‘192.168.0.10-80‘ for key ‘host‘聯合唯一
四 primary key
從約束角度看primary key字段的值不為空且唯一,那我們直接使用not null+unique不就可以了嗎,要它幹什麽?
主鍵primary key是innodb存儲引擎組織數據的依據,innodb稱之為索引組織表,一張表中必須有且只有一個主鍵。
一個表中可以:
單列做主鍵
多列做主鍵(復合主鍵)
============單列做主鍵=============== #方法一:not null+unique create table department1( id int not null unique, #主鍵 name varchar(20) not null unique, comment varchar(100) ); mysql> desc department1; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | NO | UNI | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.01 sec) #方法二:在某一個字段後用primary key create table department2( id int primary key, #主鍵 name varchar(20), comment varchar(100) ); mysql> desc department2; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.00 sec) #方法三:在所有字段後單獨定義primary key create table department3( id int, name varchar(20), comment varchar(100), constraint pk_name primary key(id); #創建主鍵並為其命名pk_name mysql> desc department3; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.01 sec)單列主鍵
==================多列做主鍵================ create table service( ip varchar(15), port char(5), service_name varchar(10) not null, primary key(ip,port) ); mysql> desc service; +--------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+-------------+------+-----+---------+-------+ | ip | varchar(15) | NO | PRI | NULL | | | port | char(5) | NO | PRI | NULL | | | service_name | varchar(10) | NO | | NULL | | +--------------+-------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql> insert into service values -> (‘172.16.45.10‘,‘3306‘,‘mysqld‘), -> (‘172.16.45.11‘,‘3306‘,‘mariadb‘) -> ; Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into service values (‘172.16.45.10‘,‘3306‘,‘nginx‘); ERROR 1062 (23000): Duplicate entry ‘172.16.45.10-3306‘ for key ‘PRIMARY‘多列主鍵
五 auto_increment
約束字段為自動增長,被約束的字段必須同時被key約束
#不指定id,則自動增長 create table student( id int primary key auto_increment, name varchar(20), sex enum(‘male‘,‘female‘) default ‘male‘ ); mysql> desc student; +-------+-----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | | sex | enum(‘male‘,‘female‘) | YES | | male | | +-------+-----------------------+------+-----+---------+----------------+ mysql> insert into student(name) values -> (‘egon‘), -> (‘alex‘) -> ; mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 1 | egon | male | | 2 | alex | male | +----+------+------+ #也可以指定id mysql> insert into student values(4,‘asb‘,‘female‘); Query OK, 1 row affected (0.00 sec) mysql> insert into student values(7,‘wsb‘,‘female‘); Query OK, 1 row affected (0.00 sec) mysql> select * from student; +----+------+--------+ | id | name | sex | +----+------+--------+ | 1 | egon | male | | 2 | alex | male | | 4 | asb | female | | 7 | wsb | female | +----+------+--------+ #對於自增的字段,在用delete刪除後,再插入值,該字段仍按照刪除前的位置繼續增長 mysql> delete from student; Query OK, 4 rows affected (0.00 sec) mysql> select * from student; Empty set (0.00 sec) mysql> insert into student(name) values(‘ysb‘); mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 8 | ysb | male | +----+------+------+ #應該用truncate清空表,比起delete一條一條地刪除記錄,truncate是直接清空表,在刪除大表時用它 mysql> truncate student; Query OK, 0 rows affected (0.01 sec) mysql> insert into student(name) values(‘egon‘); Query OK, 1 row affected (0.01 sec) mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 1 | egon | male | +----+------+------+ 1 row in set (0.00 sec)View Code
了解知識
#在創建完表後,修改自增字段的起始值 mysql> create table student( -> id int primary key auto_increment, -> name varchar(20), -> sex enum(‘male‘,‘female‘) default ‘male‘ -> ); mysql> alter table student auto_increment=3; mysql> show create table student; ....... ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 mysql> insert into student(name) values(‘egon‘); Query OK, 1 row affected (0.01 sec) mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 3 | egon | male | +----+------+------+ row in set (0.00 sec) mysql> show create table student; ....... ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 #也可以創建表時指定auto_increment的初始值,註意初始值的設置為表選項,應該放到括號外 create table student( id int primary key auto_increment, name varchar(20), sex enum(‘male‘,‘female‘) default ‘male‘ )auto_increment=3; #設置步長 sqlserver:自增步長 基於表級別 create table t1( id int。。。 )engine=innodb,auto_increment=2 步長=2 default charset=utf8 mysql自增的步長: show session variables like ‘auto_inc%‘; #基於會話級別 set session auth_increment_increment=2 #修改會話級別的步長 #基於全局級別的 set global auth_increment_increment=2 #修改全局級別的步長(所有會話都生效) #!!!註意了註意了註意了!!! If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. 翻譯:如果auto_increment_offset的值大於auto_increment_increment的值,則auto_increment_offset的值會被忽略 ,這相當於第一步步子就邁大了,扯著了蛋 比如:設置auto_increment_offset=3,auto_increment_increment=2 mysql> set global auto_increment_increment=5; Query OK, 0 rows affected (0.00 sec) mysql> set global auto_increment_offset=3; Query OK, 0 rows affected (0.00 sec) mysql> show variables like ‘auto_incre%‘; #需要退出重新登錄 +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | auto_increment_increment | 1 | | auto_increment_offset | 1 | +--------------------------+-------+ create table student( id int primary key auto_increment, name varchar(20), sex enum(‘male‘,‘female‘) default ‘male‘ ); mysql> insert into student(name) values(‘egon1‘),(‘egon2‘),(‘egon3‘); mysql> select * from student; +----+-------+------+ | id | name | sex | +----+-------+------+ | 3 | egon1 | male | | 8 | egon2 | male | | 13 | egon3 | male | +----+-------+------+步長:auto_increment_increment,起始偏移量:auto_increment_offset
六 foreign key
一 快速理解foreign key
員工信息表有三個字段:工號 姓名 部門
公司有3個部門,但是有1個億的員工,那意味著部門這個字段需要重復存儲,部門名字越長,越浪費
解決方法:
我們完全可以定義一個部門表
然後讓員工信息表關聯該表,如何關聯,即foreign key
#表類型必須是innodb存儲引擎,且被關聯的字段,即references指定的另外一個表的字段,必須保證唯一 create table department( id int primary key, name varchar(20) not null )engine=innodb; #dpt_id外鍵,關聯父表(department主鍵id),同步更新,同步刪除 create table employee( id int primary key, name varchar(20) not null, dpt_id int, constraint fk_name foreign key(dpt_id) references department(id) on delete cascade on update cascade )engine=innodb; #先往父表department中插入記錄 insert into department values (1,‘歐德博愛技術有限事業部‘), (2,‘艾利克斯人力資源部‘), (3,‘銷售部‘); #再往子表employee中插入記錄 insert into employee values (1,‘egon‘,1), (2,‘alex1‘,2), (3,‘alex2‘,2), (4,‘alex3‘,2), (5,‘李坦克‘,3), (6,‘劉飛機‘,3), (7,‘張火箭‘,3), (8,‘林子彈‘,3), (9,‘加特林‘,3) ; #刪父表department,子表employee中對應的記錄跟著刪 mysql> delete from department where id=3; mysql> select * from employee; +----+-------+--------+ | id | name | dpt_id | +----+-------+--------+ | 1 | egon | 1 | | 2 | alex1 | 2 | | 3 | alex2 | 2 | | 4 | alex3 | 2 | +----+-------+--------+ #更新父表department,子表employee中對應的記錄跟著改 mysql> update department set id=22222 where id=2; mysql> select * from employee; +----+-------+--------+ | id | name | dpt_id | +----+-------+--------+ | 1 | egon | 1 | | 3 | alex2 | 22222 | | 4 | alex3 | 22222 | | 5 | alex1 | 22222 | +----+-------+--------+示範
二 如何找出兩張表之間的關系
分析步驟: #1、先站在左表的角度去找 是否左表的多條記錄可以對應右表的一條記錄,如果是,則證明左表的一個字段foreign key 右表一個字段(通常是id) #2、再站在右表的角度去找 是否右表的多條記錄可以對應左表的一條記錄,如果是,則證明右表的一個字段foreign key 左表一個字段(通常是id) #3、總結: #多對一: 如果只有步驟1成立,則是左表多對一右表 如果只有步驟2成立,則是右表多對一左表 #多對多 如果步驟1和2同時成立,則證明這兩張表時一個雙向的多對一,即多對多,需要定義一個這兩張表的關系表來專門存放二者的關系 #一對一: 如果1和2都不成立,而是左表的一條記錄唯一對應右表的一條記錄,反之亦然。這種情況很簡單,就是在左表foreign key右表的基礎上,將左表的外鍵字段設置成unique即可
三 建立表之間的關系
#一對多或稱為多對一 三張表:出版社,作者信息,書 一對多(或多對一):一個出版社可以出版多本書 關聯方式:foreign key
=====================多對一===================== create table press( id int primary key auto_increment, name varchar(20) ); create table book( id int primary key auto_increment, name varchar(20), press_id int not null, foreign key(press_id) references press(id) on delete cascade on update cascade ); insert into press(name) values (‘北京工業地雷出版社‘), (‘人民音樂不好聽出版社‘), (‘知識產權沒有用出版社‘) ; insert into book(name,press_id) values (‘九陽神功‘,1), (‘九陰真經‘,2), (‘九陰白骨爪‘,2), (‘獨孤九劍‘,3), (‘降龍十巴掌‘,2), (‘葵花寶典‘,3) ;View Code
一夫多妻制 #妻子表的丈夫id外鍵到丈夫表的id其他例子
#多對多 三張表:出版社,作者信息,書 多對多:一個作者可以寫多本書,一本書也可以有多個作者,雙向的一對多,即多對多 關聯方式:foreign key+一張新的表
=====================多對多===================== create table author( id int primary key auto_increment, name varchar(20) ); #這張表就存放作者表與書表的關系,即查詢二者的關系查這表就可以了 create table author2book( id int not null unique auto_increment, author_id int not null, book_id int not null, constraint fk_author foreign key(author_id) references author(id) on delete cascade on update cascade, constraint fk_book foreign key(book_id) references book(id) on delete cascade on update cascade, primary key(author_id,book_id) ); #插入四個作者,id依次排開 insert into author(name) values(‘egon‘),(‘alex‘),(‘yuanhao‘),(‘wpq‘); #每個作者與自己的代表作如下 1 egon: 1 九陽神功 2 九陰真經 3 九陰白骨爪 4 獨孤九劍 5 降龍十巴掌 6 葵花寶典 2 alex: 1 九陽神功 6 葵花寶典 3 yuanhao: 4 獨孤九劍 5 降龍十巴掌 6 葵花寶典 4 wpq: 1 九陽神功 insert into author2book(author_id,book_id) values (1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (2,1), (2,6), (3,4), (3,5), (3,6), (4,1) ;View Code
單張表:用戶表+相親關系表,相當於:用戶表+相親關系表+用戶表 多張表:用戶表+用戶與主機關系表+主機表 中間那一張存放關系的表,對外關聯的字段可以聯合唯一其他例子
#一對一 兩張表:學生表和客戶表 一對一:一個學生是一個客戶,一個客戶有可能變成一個學校,即一對一的關系 關聯方式:foreign key+unique
#一定是student來foreign key表customer,這樣就保證了: #1 學生一定是一個客戶, #2 客戶不一定是學生,但有可能成為一個學生 create table customer( id int primary key auto_increment, name varchar(20) not null, qq varchar(10) not null, phone char(16) not null ); create table student( id int primary key auto_increment, class_name varchar(20) not null, customer_id int unique, #該字段一定要是唯一的 foreign key(customer_id) references customer(id) #外鍵的字段一定要保證unique on delete cascade on update cascade ); #增加客戶 insert into customer(name,qq,phone) values (‘李飛機‘,‘31811231‘,13811341220), (‘王大炮‘,‘123123123‘,15213146809), (‘守榴彈‘,‘283818181‘,1867141331), (‘吳坦克‘,‘283818181‘,1851143312), (‘贏火箭‘,‘888818181‘,1861243314), (‘戰地雷‘,‘112312312‘,18811431230) ; #增加學生 insert into student(class_name,customer_id) values (‘脫產3班‘,3), (‘周末19期‘,4), (‘周末19期‘,5) ;View Code
例一:一個用戶只有一個博客 用戶表: id name 1 egon 2 alex 3 wupeiqi 博客表 fk+unique id url name_id 1 xxxx 1 2 yyyy 3 3 zzz 2 例二:一個管理員唯一對應一個用戶 用戶表: id user password 1 egon xxxx 2 alex yyyy 管理員表: fk+unique id user_id password 1 1 xxxxx 2 2 yyyyy其他例子
mysql 完整性約束