not null约束
not null 约束只能在列名后面声明,不能使用constraint语句声明,当然也就没无法声明约束名称了。更改字段为null或者not null只能使用alter table table_name modify col_name (not) null;无法使用constraint语句修改。也就是说not null虽然是约束,但是却和constraint语句扯不上关系。not null约束在information_schema里面的table_constraints表中也无法查到。
(1)在创建表的时候申明not null 约束
create table t1(id int primary key, name varchar(20) not null);
(2)在表已经存在时为字段添加not null约束
alter table t2 modify name varchar(20) not null;
(3)删除not null 约束
alter table t2 modify name varchar(20) null;
主键约束
主键约束既可以在列名后面声明,也可以在声明完所有列之后声明。前者只需要在列明后面跟上primary key就行了,后者的声明方法是[CONSTRAINT [symbol]] PRIMARY KEY(COL1,...),这里声明约束名称是没有任何意义的(只针对MySQL),因为你假如使用CONSTRAINT [symbol]语句之后,MySQL会自动把约束名称改为PRIMARY,可以到information_schema里面的table_constriants表里面验证。所以我们在声明所有列再声明primary key一般都不会使用constraint关键字。主键即唯一索引加上not null约束,主键列上会创建唯一索引,索引的名称和约束名称相同(都为PRIMARY),默认为BTREE索引,索引信息可以在information_schema里面的statistics表里面查询。
(1)在创建表的时候申明主键约束
create table t1(id int primary key, name varchar(20);
create table t1(id int, name varchar(20), primary key(id));=========>常用
create table t1(id int, name varchar(20), constraint ti_t1_pk primary key(id));=======>约束名没有意义
(2)在表已经存在的时候添加主键约束
alter table t1 modify id int primary key;
alter table t1 add primary key(id); =========>常用,不过建表不带主键是不明智的行为
alter table t1 add constraint t1_id_pk primary key(id);=======>约束名没有意义
(3)删除主键约束
alter table table_name drop primary key;
unique约束
unique约束和unique索引(注意是unique索引,不是普通索引)有着微妙的关系,二者在MySQL里面是同时存在的,但是二者不能等价。unique约束可以在information_schema里面的table_constraints表中查到,索引信息可以在information_schema里面的statistics表里面查询。
(1)创建表的时候可以使用如下几种方法创建unique约束:
create table t1(id int primary key,name varchar(20) unique);=======>无法指定约束名称,系统默认约束名称和字段名相同。
create table t1(id int primary key,name varchar(20),constraint t1_unq unique(name));========>指定了约束名(或者索引名)。如果省略constraint子句或者只省略约束名称,那么约束名称和字段名相同。
create table t1(id int primary key,name varchar(20), unique index t1_name_unq(name));========>常用,相当于创建了索引。
create table t1(id int primary key,name varchar(20), unique key t1_name_unq(name));========>同上,相当于创建了索引,只是用的关键字是key,index和key在MySQL里面是同义词
(2)表已经存在时可以通过两种方式添加unique约束。
alter table t1 modify name varchar(20) unique;======>无法指定约束名称,系统默认约束名称和字段名相同。
alter table t1 add constraint t1_name_unq unique(name);======>constraint关键字指定约束名称,即索引名称。如果省略约束名或者constraint关键字和约束名,那么约束名和字段名相同。
alter table t1 add unique index t1_name_unq(name);=======>常用,约束名和索引名都为t1_name_unq
alter table t1 add unique key t1_name_unq(name);=======>同上,相当于创建了索引,只是用的关键字是key
因为unique约束和unique索引同时存在,所以我们都会用第三种方式去添加unique索(t1_name_unq为索引名称),如果不带unique关键字则说明添加的是普通索引。unique约束(unique索引)的信息会同时在information_schema里面的statistics表和table_constraints表里面保持一致。
(3)删除unique约束(索引)只能使用如下语句:
alter table t1 drop index t1_unq;
外键约束
(1)在建表时创建外键约束可以使用如下方法(注意被引用的表的那个列必须是主键或者有unique索引):
create table t1(id int primary key,name varchar(20), constraint t1_fk_name foreign key(name) references t2(name));该方法可以声明约束名。========>常用,如果省略contraint子句或者只省略约束名称,系统会按照一定的规则指定一个约束名称
(2)在表已经存在的时候添加外键约束可以使用如下语句:
alter table t1 add constraint t1_fk_name foreign key(name) references t2(name));=======>如果不指定constraint子句或者只省略约束名称,系统会按照一定的规则指定一个约束名
(3)删除外键使用如下语句:
alter table t1 drop foreign key t1_fk_name;
注意1:InnoDB和Myisam引擎为比较常用的引擎。近年来大家越来越偏好采用InnoDB,因为它支持事务和外键。Myisam引擎不支持事务也不支持外键,如果你在Myisam引擎中创建外键,语句不会报错,但是show create table的显示是看不到外键的。 另外,在InnoDB表中创建指向Myisam表的外键,语句会报错Cannot add foreign key constraint。
注意2:创建外键的父表的字段必须是主键或者有索引(只是普通索引即可,不一定要非空,也不一定是唯一索引)。主表和子表的字段数据类型要相同,数据类型相同指的是数据类型,不包括长度。比如varchar(5)和varchar(10)数据类型相同,varchar(10)和char(5)数据类型相同,而init、smallint和bigint等数据类型则不相同(实验得出的结论)。如果不符合这个条件会报错Cannot add foreign key constraint。不过一般情况下我们还是设置父子表的字段类型和长度都一样。
check约束
MySQL不支持check约束。如果你在SQL语句中写check约束,MySQL不会报错,但是没有任何效果。你必须在程序里面去限制列的取值。
试验如下:
mysql> create table t4(id int, age int, constraint t1_age_check check(age>18)); ======>没有报错
Query OK, 0 rows affected (0.11 sec)
mysql> show create table t4\G======>没有check约束的信息
*************************** 1. row ***************************
Table: t4
Create Table: CREATE TABLE `t4` (
`id` int(11) DEFAULT NULL,
`age` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> insert into t4 values(1,20);======>仍然可以插入数据
Query OK, 1 row affected (0.01 sec)
可以看到check约束是没有任何作用的。当然了,使用modify语句添加或修改check约束是没有用的,在information_schema库的table_constraints表中同样也是无法查到的。
总结:
1. not null是一朵奇葩。只能在列级指定。
2. primary key的约束名称是没有意义的。你指定了MySQL也会把你重置为PRIMARY。
3. 除了not null约束,一般建表的时候所有的约束都放在表级声明(包括primary key),只是因为放在那里一目了然,便于查看和维护。
4. 除了not null约束,添加约束的时候都最好使用alter table add ....语句,删除约束的时候都最好使用alter table drop ....语句,这样便于记忆。