MySQL四-2:完整性約束
阿新 • • 發佈:2017-09-12
建表 mysqld ext 基本原理 初始 sql 客戶 都是 插入記錄
閱讀目錄
- 一 介紹
- 二 not null與default
- 三 unique
- 四 primary key
- 五 auto_increment
- 六 foreign key
- 七 作業
一 介紹
約束條件與數據類型的寬度一樣,都是可選參數
作用:用於保證數據的完整性和一致性
主要分為:
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‘
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 | | +-------+---------+------+-----+---------+-------+ 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字段的值不為空且唯一
一個表中可以:
單列做主鍵
多列做主鍵(復合主鍵)
但一個表內只能有一個主鍵primary key
============單列做主鍵=============== #方法一: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 | | +--------------+-------------+------+-----+---------+-------+ 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 | +----+------+------+ 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 | +----+-------+------+步長increment與起始偏移量offset:auto_increment_increment,auto_increment_offset
六 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 表2
則表1的多條記錄對應表2的一條記錄,即多對一
利用foreign key的原理我們可以制作兩張表的多對多,一對一關系
多對多:
表1的多條記錄可以對應表2的一條記錄
表2的多條記錄也可以對應表1的一條記錄
一對一:
表1的一條記錄唯一對應表2的一條記錄,反之亦然
分析時,我們先從按照上面的基本原理去套,然後再翻譯成真實的意義,就很好理解了
輔助理解
#一對多或稱為多對一 三張表:出版社,作者信息,書 一對多(或多對一):一個出版社可以出版多本書 關聯方式: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
單張表:用戶表+相親關系表,相當於:用戶表+相親關系表+用戶表 多張表:用戶表+用戶與主機關系表+主機表 中間那一張存放關系的表,對外關聯的字段可以聯合唯一其它例子
#一對一 兩張表:學生表和客戶表 一對一:一個學生是一個客戶,一個客戶有可能變成一個學校,即一對一的關系 關聯方式:foreign key+unique
例一:一個用戶只有一個博客 用戶表: id name egon alex wupeiqi 博客表 fk+unique id url name_id xxxx 1 yyyy 3 zzz 2 例二:一個管理員唯一對應一個用戶 用戶表: id user password egon xxxx alex yyyy 管理員表: fk+unique id user_id password 1 xxxxx 2 yyyyy其他例子
七 作業
練習:賬號信息表,用戶組,主機表,主機組
#用戶表 create table user( id int not null unique auto_increment, username varchar(20) not null, password varchar(50) not null, primary key(username,password) ); insert into user(username,password) values (‘root‘,‘123‘), (‘egon‘,‘456‘), (‘alex‘,‘alex3714‘) ; #用戶組表 create table usergroup( id int primary key auto_increment, groupname varchar(20) not null unique ); insert into usergroup(groupname) values (‘IT‘), (‘Sale‘), (‘Finance‘), (‘boss‘) ; #主機表 create table host( id int primary key auto_increment, ip char(15) not null unique default ‘127.0.0.1‘ ); insert into host(ip) values (‘172.16.45.2‘), (‘172.16.31.10‘), (‘172.16.45.3‘), (‘172.16.31.11‘), (‘172.10.45.3‘), (‘172.10.45.4‘), (‘172.10.45.5‘), (‘192.168.1.20‘), (‘192.168.1.21‘), (‘192.168.1.22‘), (‘192.168.2.23‘), (‘192.168.2.223‘), (‘192.168.2.24‘), (‘192.168.3.22‘), (‘192.168.3.23‘), (‘192.168.3.24‘) ; #業務線表 create table business( id int primary key auto_increment, business varchar(20) not null unique ); insert into business(business) values (‘輕松貸‘), (‘隨便花‘), (‘大富翁‘), (‘窮一生‘) ; #建關系:user與usergroup create table user2usergroup( id int not null unique auto_increment, user_id int not null, group_id int not null, primary key(user_id,group_id), foreign key(user_id) references user(id), foreign key(group_id) references usergroup(id) ); insert into user2usergroup(user_id,group_id) values (1,1), (1,2), (1,3), (1,4), (2,3), (2,4), (3,4) ; #建關系:host與business create table host2business( id int not null unique auto_increment, host_id int not null, business_id int not null, primary key(host_id,business_id), foreign key(host_id) references host(id), foreign key(business_id) references business(id) ); insert into host2business(host_id,business_id) values (1,1), (1,2), (1,3), (2,2), (2,3), (3,4) ; #建關系:user與host create table user2host( id int not null unique auto_increment, user_id int not null, host_id int not null, primary key(user_id,host_id), foreign key(user_id) references user(id), foreign key(host_id) references host(id) ); insert into user2host(user_id,host_id) values (1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (2,2), (2,3), (2,4), (2,5), (3,10), (3,11), (3,12);View Code
作業:
MySQL四-2:完整性約束