myql之完整性約束
一 介紹
約束條件與數據類型的寬度一樣,都是可選參數
作用:用於保證數據的完整性和一致性
主要分為:
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(
id 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 (key)(*****)
============設置唯一約束 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‘唯一約束unique
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) 這是由於mysql內部存儲和查找機制決定的,mysql內部存儲查找都是基於索引的,這就要求每一個表都必須有一個主鍵primary key,mysql就會依據這個key來組織數據,這樣可以優化查找速度,相當於目錄, 也就是說,如果你創建表是沒有指定主鍵,那麽mysql會從上自下自動查找你的定義字段,只要遇到非空和唯一字段,就會自動將其設置為主鍵,而如果非空且唯一字段也沒有的話,那麽mysql會默認用自帶的隱藏主鍵,但是這樣的話就喪失優化查找的能力,大大降低了效率。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 | | +--------------+-------------+------+-----+---------+-------+ 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約束(unique key,primary 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)自增在用delete刪除後會發生什麽?
了解知識
#在創建完表後,修改自增字段的起始值 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
六 總結
not null與default
unique唯一
主鍵
#primary key:單單從約束角度去看,primary key就等同於not null unique
#強調(******)
1、一張表中必須有,並且只能有一個主鍵
2、一張表中都應該有一個id字段,而且應該把id字段做成主鍵
create table t17(
id int primary key,
name char(16),
age int,
sex char(6)
)engine=innodb;
#聯合主鍵
create table t19(
ip char(15),
port int,
primary key(ip,port)
);
# primary key auto_increment
create table t20(
id int primary key auto_increment,
name char(16)
)engine=innodb;
# auto_increment註意點:
1、通常與primary key連用,而且通常是給id字段加
2、auto_incremnt只能給被定義成key(unique key,primary key)的字段加
myql之完整性約束