文章目录
- 0. 前言
- 1. 空属性
- 2. 默认值
- 3. 列描述
- 4. zerofill
- 5. 主键
- 6. 自增长
- 7. 唯一键
- 8. 外键
0. 前言
-
真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。比如有一个字段是email,要求是唯一的。
表的约束很多,这里主要介绍如下几个: null/not null,default, comment, zerofill,primary key,auto_increment,unique key
-
表的结构
1. 空属性
- 两个值:null(默认的)和not null(不为空)
- 数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。
案例:
创建一个班级表,包含班级名和班级所在的教室。(班级和教室不能为空)
mysql> system clear
mysql> system clear;
mysql> create table myclass(
-> class_name varchar(20) not NULL,
-> class_room varchar(10) not NULL
-> );
Query OK, 0 rows affected (0.18 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into myclass values(NULL, NULL);
ERROR 1048 (23000): Column 'class_name' cannot be null
mysql> insert into myclass values();
ERROR 1364 (HY000): Field 'class_name' doesn't have a default value
2. 默认值
- 默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,
用户可以选择性的使用默认值(就是不再显示填写)。
案例:
mysql> create table tt8(
-> name varchar(20) not NULL,
-> age tinyint unsigned default 18,
-> sex char(1) default '女'
-> );
Query OK, 0 rows affected (0.27 sec)
mysql> desc tt8;
+-------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| name | varchar(20) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| sex | char(1) | YES | | 女 | |
+-------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
默认值生效
mysql> insert into tt8(name) values('刘亦菲');
Query OK, 1 row affected (0.03 sec)
mysql> select * from tt8;
+-----------+------+------+
| name | age | sex |
+-----------+------+------+
| 刘亦菲 | 18 | 女 |
+-----------+------+------+
1 row in set (0.00 sec)
3. 列描述
- 列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存。就类似于代码中的注释。
案例:
mysql> create table tt9(
-> name varchar(20) not NULL comment '姓名',
-> age tinyint unsigned default 18 comment '年龄',
-> sex char(1) default '女' comment '性别'
-> );
Query OK, 0 rows affected (0.14 sec)
mysql> desc tt9;
+-------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| name | varchar(20) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| sex | char(1) | YES | | 女 | |
+-------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
desc 查看不到注释信息,通过show查看创建完整指令可以看见。
mysql> show create table tt9\G
*************************** 1. row ***************************
Table: tt9
Create Table: CREATE TABLE `tt9` (
`name` varchar(20) NOT NULL COMMENT '姓名',
`age` tinyint(3) unsigned DEFAULT '18' COMMENT '年龄',
`sex` char(1) DEFAULT '女' COMMENT '性别'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.01 sec)
4. zerofill
可以看到int(11),这个代表什么意思呢?这个10代表什么呢?其实没有zerofill这个属性,括号内的数字是毫无意义的。
mysql> create table `tt10`(
-> a int,
-> b int
-> );
Query OK, 0 rows affected (0.21 sec)
mysql> insert into `tt10` values(1, 2);
Query OK, 1 row affected (0.02 sec)
mysql> show create table `tt10`\G
*************************** 1. row ***************************
Table: tt10
Create Table: CREATE TABLE `tt10` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> select * from `tt10`;
+------+------+
| a | b |
+------+------+
| 1 | 2 |
+------+------+
1 row in set (0.00 sec)
alter table `tt10` change a a int(5) unsigned zerofill;
mysql> select * from `tt10`;
+-------+------+
| a | b |
+-------+------+
| 00001 | 2 |
+-------+------+
1 row in set (0.00 sec)
// 实际完整写法如下:
mysql> show create table `tt10`\G
*************************** 1. row ***************************
Table: tt10
Create Table: CREATE TABLE `tt10` (
`a` int(5) unsigned zerofill DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
实际上zerofill属性的作用:宽度小于设定的宽度(这里设置的是5),前面自动填充0。
实际上存的值还是1,调用函数hex来证明.
mysql> select a, hex(a) from `tt10`;
+-------+--------+
| a | hex(a) |
+-------+--------+
| 00001 | 1 |
+-------+--------+
1 row in set (0.00 sec)
5. 主键
- 主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个。
- 主键;主键所在的列通常是整数类型。
验证:
mysql> create table `tt11`(
-> id int unsigned primary key comment '学号不能为空',
-> name varchar(20) not NULL
-> );
Query OK, 0 rows affected (0.20 sec)
mysql> insert into `tt11` values(1, '小丁');
Query OK, 1 row affected (0.04 sec)
mysql> insert into `tt11` values(1, '小花');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> insert into `tt11`(name) values('小花');
ERROR 1364 (HY000): Field 'id' doesn't have a default value
实际完整写法就包含了不能重复,不能为空
mysql> show create table `tt11`\G
*************************** 1. row ***************************
Table: tt11
Create Table: CREATE TABLE `tt11` (
`id` int(10) unsigned NOT NULL COMMENT '学号不能为空',
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
- 主键约束:主键对应的字段中不能重复,一旦重复,操作失败。
mysql> insert into `tt11` values(1, '小丁');
Query OK, 1 row affected (0.04 sec)
mysql> insert into `tt11` values(1, '小花');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
- 删除主键
alter table 表名 drop primary key;
mysql> alter table `tt11` drop primary key;
Query OK, 1 row affected (0.53 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert into `tt11` values(1, '小花');
Query OK, 1 row affected (0.04 sec)
mysql> select * from `tt11`;
+----+--------+
| id | name |
+----+--------+
| 1 | 小丁 |
| 1 | 小花 |
+----+--------+
2 rows in set (0.00 sec)
- 追加主键:追加主键的字段表一定要符合主键的性质
alter table 表名 add primary key(字段列表);
mysql> alter table `tt11` add primary key(id);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> alter table `tt11` add primary key(name);
Query OK, 0 rows affected (0.41 sec)
Records: 0 Duplicates: 0 Warnings: 0
// name字段可以成为主键
mysql> desc `tt11`;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | NO | | NULL | |
| name | varchar(20) | NO | PRI | NULL | |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
- 复合主键
id和course为复合主键
mysql> create table `tt12`(
-> id int unsigned,
-> score tinyint unsigned default 60 comment '成绩',
-> primary key(id, score)
-> );
复合主键特点:id和course只要不完成相同就没事
mysql> select * from `tt12`;
+----+-------+
| id | score |
+----+-------+
| 1 | 60 |
| 1 | 99 |
| 2 | 60 |
+----+-------+
3 rows in set (0.01 sec)
6. 自增长
- auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同的值。
- 通常和主键搭配使用,作为逻辑主键。
mysql> create table `tt13`(
-> id int unsigned primary key auto_increment,
-> name varchar(20) not NULL default ''
-> );
Query OK, 0 rows affected (0.19 sec)
mysql> insert into `tt13` values('a');
ERROR 1136 (21S01): Column count doesn't match value count at row 1
mysql> insert into `tt13`(name) values('a');
Query OK, 1 row affected (0.04 sec)
mysql> insert into `tt13`(name) values('b');
Query OK, 1 row affected (0.03 sec)
mysql> insert into `tt13` values();
Query OK, 1 row affected (0.03 sec)
mysql> select * from `tt13`;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | |
+----+------+
3 rows in set (0.00 sec)
改下自增长起始值
mysql> insert into `tt13` values(10001, '马化腾');
Query OK, 1 row affected (0.02 sec)
mysql> insert into `tt13`(name) values('c');
Query OK, 1 row affected (0.04 sec)
mysql> select * from `tt13`;
+-------+-----------+
| id | name |
+-------+-----------+
| 1 | a |
| 2 | b |
| 3 | |
| 10001 | 马化腾 |
| 10002 | c |
+-------+-----------+
5 rows in set (0.00 sec)
- 自增长的特点:
- 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
- 自增长字段必须是整数
- 一张表最多只能有一个自增长
7. 唯一键
- 唯一键与主键
一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键:唯一键可以解决表中有多个字段需要唯一性约束的问题。
案例:
mysql> create table `tt14`(
-> id int unsigned primary key auto_increment,
-> student_id char(10) not NULL unique comment '学号不能重复'
-> );
Query OK, 0 rows affected (0.21 sec)
mysql> insert into `tt14`(student_id) values(1234);
Query OK, 1 row affected (0.02 sec)
mysql> insert into `tt14`(student_id) values(1234);
ERROR 1062 (23000): Duplicate entry '1234' for key 'student_id' -- 学号重复,报错。
mysql> select * from `tt14`;
+----+------------+
| id | student_id |
+----+------------+
| 1 | 1234 |
+----+------------+
1 row in set (0.00 sec)
注意:
唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。
alter table `tt14` change student_id student_id char(10) unique comment '学号不为空,可以重复';
mysql> insert into `tt14` values();
Query OK, 1 row affected (0.02 sec)
mysql> insert into `tt14` values();
Query OK, 1 row affected (0.02 sec)
// 最好在插入数据前就设计好。
mysql> select * from `tt14`;
+----+------------+
| id | student_id |
+----+------------+
| 3 | NULL |
| 4 | NULL |
| 1 | 1234 |
+----+------------+
3 rows in set (0.00 sec)
8. 外键
-
外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。
-
语法
foreign key (字段名) references 主表(列)
案例:
- 创建主键表
create table `myclass`(
-> id int primary key,
-> name varchar(20) not NULL comment '班级名'
-> );
- 创建从表
create table `stu`(
-> id int primary key,
-> name varchar(30) not NULL comment '学生名',
-> class_id int,
-> foreign key(class_id) references `myclass`(id)
-> );
- 正常插入数据
mysql> insert into `myclass` values(10, '104班'), (20, '105班');
Query OK, 2 rows affected (0.03 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into `stu` values(100, '张三', 10), (101, '李四', 20);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
- 插入主键表不存在的班级,插入失败
mysql> insert into `stu` values(102, '李欢', 30);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`person`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `myclass` (`id`))