通过约束可以更好的保证数据表里数据的完整性。
约束是在表上强制执行的数据检验规则,约束主要用于保证数据库里数据的完整性。
当表中数据存在相互依赖性时,可以保护相关数据不被删除。
大部分数据库支持下面5种完整性约束。
- NOT NULL:非空约束,指定某列不能为空。
- UNIQUE:唯一约束,指定某列或者几列组合不能重复。
- PRIMARY KEY: 主键,指定该列的值可以唯一的标识该条记录。
- FOREIGN KEY:外键,指定该列记录从属于主表中的一条记录,主要用于保证参照完整性。
- CHECK:检查,指定一个布尔表达式,用于指定对应列的值必须满足该表达式。
注意: MySQL不支持CHECK约束,虽然MySQL的SQL语句也可以使用CHECK约束,但不会起任何作用。
根据约束对数据列的限制,约束分为如下两类:
- 单列约束:每个约束只约束一列。
- 多列约束:每个约束可以约束多列。
为数据表指定约束的时机
- 建表的同时为相应的数据列指定约束
- 建表后创建,以修改表的方式来增加约束
5中约束的建立和删除(约束通常无法修改)。
1.NOT NULL约束
非空约束用于确保指定列不允许为空,非空约束是比较特殊的约束,它只能作为列级约束使用,只能使用列级约束语法定义。
建表时为指定列指定非空约束,只要在列定义后增加not null即可,语句如下
create table test_one
(
test_one_id int not null, // 建立非空约束
test_one_name varchar(255) default 'xyz' not null, // Mysql的非空约束不能指定名字
test_one_gender varchar(2) null // 默认为空
);
在使用alter table修改表时增加或删除非空约束,SQL命令如下:
// 增加非空约束
alter table test_one
modify test_one_gender varchar(2) not null;
// 取消非空约束
alter table test_one
modify test_one_gender varchar(2) null;
// 取消非空约束并指定默认值
alter table test_one
modify test_one_name varchar(255) default 'abc' null;
2.UNIQUE 约束
唯一约束用于保证指定列或指定列组合不允许出现重复值。但允许重复出现多个null值。
同一个表中可建多个唯一约束,唯一约束也可以由多列组合而成。
唯一约束既可以使用列级约束语法建立,也可以使用表级约束语法建立。如果需要为多列建组合约束,或者需要为唯一约束指定约束名,则只能用表级约束语法。
使用列级约束语法建立唯一约束,只需要在列定义后边增加unique关键字即可。SQL语法如下:
// 建表时创建唯一约束,使用列级语法建立约束
create table unique_test(
// 建立非空约束
test_name varchar(255) not null,
// unique 就是唯一约束,列级语法建立唯一约束
test_id int unique
);
使用表级语法为多列组合建立唯一约束,或者想自行指定约束名,SQL语句如下:
// 建表时使用表级语法建立唯一约束
create table unique_test2(//建立费空约束
test_id int not null,
test_name varchar(255),
test_pass varchar(255),
// 使用表级语法建立唯一约束
unique (test_name),
// 使用表级语法建立唯一约束,而且指定约束名
constraint test2_uk unique(test_pass));
create table unique_test3(//建立费空约束
test_id int not null,
test_name varchar(255),
test_pass varchar(255),
// 使用表级语法建立唯一约束,而且指定约束名
constraint test3_uk unique(test_name,test_pass));
修改表结构使用add增加唯一约束,SQL语句如下:
// 增加唯一约束
alter table unique_test3
add unique(test_name, test_pass);
alter table unique_test3
modify test_name varchar(255) unique;
// 删除unique_test3表上的test3_uk唯一约束
alter table unique_test3
drop index test3_uk;
3.PRIMARYKEY 约束
主键约束相当于非空约束和唯一约束,即主键约束的列既不允许出现重复值,也不允许出现null值;如果对多列组合建立主键约束,则多列里包含的每一列都不能为空,但只要求这些列组合不能重复。主键列的值可用于唯一地标识表中的一条记录。
每一个表中最多允许有一个主键,但这个主键约束可由多个数据列组合而成,主键是表中能唯一确定一行记录的字段或字段组合。
建立主键约束既可以使用列级约束语法,也可以使用表级约束语法。如果需要多个字段建立组合主键约束,则只能使用表级约束语法。使用表示约束语法建立约束时,可以为该约束指定约束名。但不管用户是否为该主键约束指定约束名,MySql总是将所有的主键约束命名为PRIMARY。
当创建主键约束时,主键约束所在列或列组合上建立对应的唯一索引。主键约束列级语法:
create table primary_test(
test_id int primary key,
test_name varchar(255));
主键约束表级语法:
create table primary_test2(
test_id int not null,
test_name varchar(255),
test_pass varchar(255),
constraint test2_pk primary key(test_id));
主键约束表级语法,多列组合主键:
create table primary_test3(
test_name varchar(255),
test_pass varchar(255),
primary key(test_name, test_pass));
删除主键约束:
alter table primary_test3
drop primary key;
表级语法增加主键约束:
alter table primary_test3
add primary key(test_name, test_pass);
列级语法增加主键约束:
alter table primary_test3
modify test_name varchar(255) primary key;
MySQL使用auto_increment来设置自增长,SQL语句如下:
create table primary_test4(
// 建立主键约束,使用自增长
test_id int auto_increment primary key,
test_name varchar(255),
test_pass varchar(255));
4.FOREIGN KEY 约束
外键约束主要用于保证一个或两个数据表之间的参照完整性,外键是构建于一个表的两个字段或者两个表的两个字段之间的参照关系。外键确保了相关的两个字段的参照关系:子表外键列的值必选在主表被参照列的值的范围之内,或者为空。
当主表的记录被从表记录参照时,主表记录不允许被删除,必须先把从表里参照该记录的所有记录全部删除后,才可以删除主表的该记录。删除主表记录时级联删除从表中所有参照该记录的从表记录。
从表外键参照只能是主表主键列或者唯一键列,这样才可保证从表记录可以准确定位到被参照的主表记录。同一个表内可以拥有多个外键。
建立外键约束时,MySQL也会为该列建立索引。
外键约束通常用于定义两个实体之间的一对多、一对一的关联关系。对于一对多的关联关系,通常在多的一端增加外键列。对于一对一的关联关系,则可任意选择一方来增加外键列,增加外键列的表叫做从表,只要为外键列增加唯一约束就可以表示一对一的关联关系了。对于多对多的关联关系,则需要额外增加一个链接表来记录它们的关联关系。
建立外键约束通用可以采用列级语法和表级语法。如果仅对单独的数据列建立外键约束,则使用列级约束语法即可;
如果需要对多列组合创建外键约束,或者需要为外键约束指定名字,则必选使用表级约束语法。
采用列级约束语法建立外键约束直接使用references关键字,references指定该列参照哪个主表,以及参照主表的哪一列:
// 为了保证从表参照主表存在,通常应该先建主表
create table teacher_table(
// auto_increment:代表数据库的自动编号策略,通常用作数据表的逻辑主键
teacher_id int auto_increment,
teacher_name varchar(255),
primary key (teacher_id));
create table student_table(
// 主键约束
student_id int auto_increment primary key,
student_name varchar(255),
// 指定java_teacher参照到teacher_table的teacher_id列
java_teacher int references teacher_table(teacher_id));
create table teacher_table1(
teacher_id int auto_increment,
teacher_name varchar(255),
primary key(teacher_id)
);
create table student_table1(
student_id int auto_increment primary key,
student_name varchar(255),
java_teacher int,
foreign key(java_teacher) references teacher_table1(teacher_id));
需要显式指定外键约束名字,则可以使用constraint来指定名字:
create table teacher_table2(
teacher_id int auto_increment,
teacher_name varcher(255),
primary key(teacher_id)
);
create table student_table2(
student_id int auto_increment primary key,
student_name varchar(255),
java_teacher int,
constraint student_teacher_fk foreign key(java_teachar) references teacher_table2(teacher_id));
建立多列组合的外键约束,则必须使用表级约束语法:
create table teacher_table3(
teacher_name varchar(255),
teacher_pass varchar(255),
primary key(teacher_name, teacher_pass));
create table student_table3(
student_id int auto_increment primary key,
student_name varchar(255),
java_teacher_name varchar(255),
java_teacher_pass varchar(255),
foreign key(java_teacher_name, java_techer_pass) references teacher_table3(teacher_name, teacher_pass));
删除外键约束:
alter table student_table3
drop foreign key student_table3_ibfk_1;
增加外键约束:
alter table student_table3
add foreign key(java_teacher_name, java_teacher_pass) references teacher_table3(teacher_name,teacher_pass);
建立自关联的外键约束:
create table foreign_test(
foreign_id int auto_increment primary key,
foreign_name varchar(255),
refer_id int,
foreign key(refer_id) references foreign_test(foreign_id));
如果想定义当删除主表记录时,从表记录也会随之删除,则需要在建立外键结束后添加on delete cascade 或添加on delete set null:
第一种是删除主表记录时,把参照主表记录的从表记录全部级联删除;
第二种是删除主表记录时,把参照主表记录的从表记录外键设为null。
create table teacher_table4(
teacher_id int auto_increment,
teacher_name varchar(255),
primary key (teacher_id));
create table student_table4(
student_id int auto_increment primary key,
student_name varchar(255),
java_teacher int,
foreign key(java_teacher) references teacher_table4(teacher_id)
on delete cascade #也可以用 on delete set null);
5.CHECK 约束
create table check_test(
emp_id int auto_increment,
emp_name varchar(255),
emp_salary decimal,
primary key (emp_id),
check(emp_salary > 0));