目录
一、概念
二、空属性
三、默认值
四、列描述
五、zerofill
六、主键
七、自增长
八、唯一键
九、外键
表的约束是数据库设计中用于确保数据完整性、有效性和一致性的规则集合,通过限制字段的取值范围或关系来防止非法数据的插入或更新。真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合 法性,从业务逻辑角度保证数据的正确性。本文主要介绍以下介个:null/not null,default, comment, zerofill,primary key,auto_increment,unique key。
数据库默认字段是可以为空,但实际在业务开发中,表中的字段应尽不为空。
//建立表结构 name字段不为空 room字段可为空
mysql> create table t1( class_name varchar(10) not null, class_room varchar(10) );
Query OK, 0 rows affected (0.02 sec)
//插入数据
mysql> insert into t1(class_name, class_room) values('计算机1班','201');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1(class_name) values('计算机2班');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1(class_room) values('203');
ERROR 1364 (HY000): Field 'class_name' doesn't have a default value
//查询表数据
mysql> select * from t1;
+---------------+------------+
| class_name | class_room |
+---------------+------------+
| 计算机1班 | 201 |
| 计算机2班 | NULL |
+---------------+------------+
2 rows in set (0.00 sec)
由上述内容可知,当字段存在为空约束时,在插入数据中该字段必须得有值,否则会报错插入失败。在上例中,name字段不为空,因此在第三次插入数据只有room字段时会报错Field 'class_name' doesn't have a default value。表中的字段默认值为NULL,如果有not null约束且未指明该字段的默认值时,在插入数据时必须给出该字段的值。
默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候, 用户可以选择性的使用默认值。
//创建表结构
mysql> create table t2(
-> class_name varchar(10) not null,
-> class_room varchar(10) default '301'
-> );
Query OK, 0 rows affected (0.02 sec)
//插入表数据
mysql> insert into t2(class_name, class_room) values ('计算机1班','201');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t2(class_name) values ('计算机2班');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t2(class_name, class_room) values ('计算机3班', null);
Query OK, 1 row affected (0.01 sec)
//查询表数据
mysql> select * from t2;
+---------------+------------+
| class_name | class_room |
+---------------+------------+
| 计算机1班 | 201 |
| 计算机2班 | 301 |
| 计算机3班 | NULL |
+---------------+------------+
3 rows in set (0.00 sec)
在上例中,name字段不为空,room字段默认值为'301',当插入数据只有name字段时,room字段将使用默认值进行数据插入。room字段指定了默认值,但是是可以插入null值的。
这里需要注意的是,非空约束和默认值约束并不冲突。
非空约束指的是字段不能为NULL,在数据库中若没有指明字段的默认值则为NULL,因此在插入数据时必须显式给出该字段的值(不可为NULL);默认值约束指的是若没有显式给出该字段的值,则采用默认值进行插入,即使给出了默认值约束,也可以显式插入NULL值。非空约束和默认值约束可同时存在。
//创建表结构
mysql> create table t3(
-> class_name varchar(10),
-> class_room varchar(10) not null default '301'
-> );
Query OK, 0 rows affected (0.01 sec)
//插入表数据
mysql> insert into t3 values('计算机1班','201');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t3(class_name) values('计算机2班');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t3(class_name, class_room) values('计算机3班', null);
ERROR 1048 (23000): Column 'class_room' cannot be null
//查询表数据
mysql> select * from t3;
+---------------+------------+
| class_name | class_room |
+---------------+------------+
| 计算机1班 | 201 |
| 计算机2班 | 301 |
+---------------+------------+
2 rows in set (0.00 sec)
列描述:没有实际含义,专门用于描述字段。
mysql> create table t4(
-> name varchar(10) not null comment '姓名',
-> age tinyint default 0 comment '年龄'
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> show create table t4 \g
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
| t4 | CREATE TABLE `t4` (
`name` varchar(10) NOT NULL COMMENT '姓名',
`age` tinyint(4) DEFAULT '0' COMMENT '年龄'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
在数据库中一些数字类型后可以带长度。
//创建表结构
mysql> create table t5(
-> a int(5),
-> b int(5)
-> );
Query OK, 0 rows affected (0.01 sec)
//插入表数据
mysql> insert into t5 values(1, 2);
Query OK, 1 row affected (0.00 sec)
//查询表数据
mysql> select * from t5;
+------+------+
| a | b |
+------+------+
| 1 | 2 |
+------+------+
1 row in set (0.00 sec)
在上例中,字段a和b的类型后面都带有数字5,通过查询表数据发现并没有任何意义,但如果带有zerofill属性,显式结果就会有所不同。
//创建表结构
mysql> create table t6(
-> a int(5) zerofill,
-> b int(5) zerofill
-> );
Query OK, 0 rows affected (0.02 sec)
//插入表数据
mysql> insert into t6 values(1, 2);
Query OK, 1 row affected (0.00 sec)
//查询表数据
mysql> select * from t6;
+-------+-------+
| a | b |
+-------+-------+
| 00001 | 00002 |
+-------+-------+
1 row in set (0.00 sec)
实际zerofill属性的作用是当插入数据长度小于设定的长度时采用0进行填充,只会改变显示结果,不会影响值本身。
主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键;主键所在的列通常是整数类型。
//创建表结构
mysql> create table t7( sno int primary key, name varchar(6) not null );
Query OK, 0 rows affected (0.02 sec)
//插入表数据
mysql> insert into t7 values(1, '张三');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t7(name) values('李四');
ERROR 1364 (HY000): Field 'sno' doesn't have a default value
mysql> insert into t7(sno, name) values(null ,'王五');
ERROR 1048 (23000): Column 'sno' cannot be null
mysql> insert into t7(sno, name) values(1 ,'赵六');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
//查询表结构
mysql> select * from t7;
+-----+--------+
| sno | name |
+-----+--------+
| 1 | 张三 |
+-----+--------+
1 row in set (0.00 sec)
由上述代码中可以看出,身为主键的字段不可重复且不能为NULL。
当表创建好后也可以追加或者删除主键。
//创建表结构
mysql> create table t8(sno int, name varchar(6));
Query OK, 0 rows affected (0.02 sec)
//追求主键
mysql> alter table t8 add primary key(sno);
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table t8 \g;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------+
| t8 | CREATE TABLE `t8` (
`sno` int(11) NOT NULL,
`name` varchar(6) DEFAULT NULL,
PRIMARY KEY (`sno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
//删除主键
mysql> alter table t8 drop primary key;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table t8 \g;
+-------+---------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+---------------------------------------------------------------------------------------------------------------------+
| t8 | CREATE TABLE `t8` (
`sno` int(11) NOT NULL,
`name` varchar(6) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
在创建表时,主键只能有一个,但可以使用多个字段作为主键,也就是复合主键。
//创建表结构
mysql> create table t9(sno int,
-> course tinyint,
-> score decimal(3,1),
-> primary key(sno, course)
-> );
//查询表结构
mysql> desc t9;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| sno | int(11) | NO | PRI | NULL | |
| course | tinyint(4) | NO | PRI | NULL | |
| score | decimal(3,1) | YES | | NULL | |
+--------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
auto_increment:当对应的字段,不显示给值会自动的被系统触发,系统会从当前字段中已经有的最大值 +1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。
//创建表结构
mysql> create table t10( id int primary key auto_increment, name varchar(6) );
Query OK, 0 rows affected (0.01 sec)
//插入表数据
mysql> insert into t10(name) values('张三');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t10(name) values('李四');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t10 values(10, '王五');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t10(name) values('赵六');
Query OK, 1 row affected (0.00 sec)
//查询表结构
mysql> select * from t10;
+----+--------+
| id | name |
+----+--------+
| 1 | 张三 |
| 2 | 李四 |
| 10 | 王五 |
| 11 | 赵六 |
+----+--------+
4 rows in set (0.00 sec)
在一些场景中例如学校登记学生信息时,将学生的学号作为主键,相应的每一个学生的手机号也应该是不重复唯一的,但是主键只有一个,那么如何保证学生的手机号也具有唯一性呢?
在数据库中往往有很多字段是需要唯一性的,但是一张表只能有一个主键,因此唯一键就可以解决表中有多个字段需要唯一性约束的问题。
唯一键的本质和主键差不多,但是唯一键允许为空,空字段不参与唯一性的比较。主键主要标识记录在表中的唯一性,而唯一键属性则确保该记录的字段不与其他记录的字段重复。
//创建表结构
mysql> create table t11(
-> sno int(10) primary key,
-> name varchar(6) not null,
-> tell int unique
-> );
Query OK, 0 rows affected (0.02 sec)
//插入表数据
mysql> insert into t11 values(1, '张三', 12345);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t11 values(2, '李四', 12345);
ERROR 1062 (23000): Duplicate entry '12345' for key 'tell'
mysql> insert into t11 values(2, '李四', 12346);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t11(sno, name) values(3, '王五');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t11(sno, name) values(4, '赵六', null);
Query OK, 1 row affected (0.01 sec)
//查询表结构
mysql> select * from t11;
+-----+--------+-------+
| sno | name | tell |
+-----+--------+-------+
| 1 | 张三 | 12345 |
| 2 | 李四 | 12346 |
| 3 | 王五 | NULL |
| 4 | 赵六 | NULL |
+-----+--------+-------+
4 rows in set (0.00 sec)
由上述内容可知,唯一键属性确保了字段在表中数据不存在重复项,也验证了NULL不参与唯一性的比较。
在一些场景中例如选课中,假如只开设了数据结构、操作系统和计算机网络三门课程,但在学生选课中出现了计算机组成原理课程,这显然是不合理的,因此就需要外键属性约束。
外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique 约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。
mysql> create table class(
-> id int primary key,
-> name varchar(10) not null unique
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> create table stu(
-> id int primary key,
-> name varchar(10) not null,
-> class_id int,
-> foreign key (class_id) references class(id)
-> );
Query OK, 0 rows affected (0.02 sec)
首先创建了两个表,一个课程表和一个选课表。
mysql> insert into class values(1, '数据结构');
Query OK, 1 row affected (0.00 sec)
mysql> insert into class values(2, '操作系统');
Query OK, 1 row affected (0.01 sec)
mysql> insert into class values(3, '计算机网络');
Query OK, 1 row affected (0.00 sec)
mysql> select * from class;
+----+-----------------+
| id | name |
+----+-----------------+
| 2 | 操作系统 |
| 1 | 数据结构 |
| 3 | 计算机网络 |
+----+-----------------+
3 rows in set (0.00 sec)
首先往课程表中插入数据数据结构、操作系统和计算机网络三门课程以及对应的id。此时往选课表中插入数据时必须时在课程表中含有的课程。对于选课表中的外键课程id可以为null(可以添加非空约束)。
mysql> insert into stu values (1, '张三', 1);
Query OK, 1 row affected (0.01 sec)
mysql> insert into stu values (2, '张三', 3);
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu values (3, '李四', 2);
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu values (4, '李四', 3);
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu values (5, '王五', 4);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))
mysql> insert into stu values (5, '王五', null);
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu(id, name) values (6, '赵六');
Query OK, 1 row affected (0.00 sec)
mysql> select * from stu;
+----+--------+----------+
| id | name | class_id |
+----+--------+----------+
| 1 | 张三 | 1 |
| 2 | 张三 | 3 |
| 3 | 李四 | 2 |
| 4 | 李四 | 3 |
| 5 | 王五 | NULL |
| 6 | 赵六 | NULL |
+----+--------+----------+
6 rows in set (0.00 sec)