MySQL 第十三章 约束(★★★★★)

十三、约束(★★★★★)

13.1 什么是约束

约束对应的英语单词:constraint

在创建表的时候,我们可以给表中的字段加上一些约束来保证这个表中数据的完整性、有效性!

约束的作用:保证表中的数据有效!

13.2 约束包括哪些

  • 非空约束:not nll
  • 唯一性约束:unique
  • 主键约束:primary key(简称PK)
  • 外键约束:foregin key(简称FK)
  • 检查约束:check(mysql不支持,oracle支持)

13.3 非空约束–not null

非空约束not null 约束的字段不能为NULL

mysql> drop table if exists t_vip;
Query OK, 0 rows affected (0.01 sec)

mysql> create table t_vip(
    -> id int,
    -> name varchar(255) not null
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> desc t_vip;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int(11)      | YES  |     | NULL    |       |
| name  | varchar(255) | NO   |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> insert into t_vip(id, name) values(1, 'zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(id, name) values(2, 'lisi');
Query OK, 1 row affected (0.00 sec)

# 注意这里
mysql> insert into t_vip(id) values(3);
ERROR 1364 (HY000): Field 'name' doesn't have a default value

拓展:

xxxx.sql 这种文件被称为 sql脚本文件。sql脚本文件中编写了大量的sql语句。

我们执行sql脚本文件的时候,该文件中所有的sql语句会全部执行!批量的执行SQL语句时,可以使用sql脚本文件。

在mysql中如何执行sql脚本?------>

mysql> source H:\vip.sql

当你执行完这个脚本文件后,你电脑上的数据库数据就有了!

13.4 唯一性约束–unique

唯一性约束unique 约束的字段不能重复,但是可以为NULL。

  • 约束直接添加到列后面的,叫做列级约束

  • 约束没有添加在列的后面,被称为表级约束

    什么时候使用表级约束?

    需要给多个字段联合起来添加某一个约束的时候,需要使用表级约束。

mysql> drop table if exists t_vip;
Query OK, 0 rows affected (0.01 sec)

mysql> create table t_vip(
    -> id int,
    -> name varchar(255) unique,	# name字段唯一性约束
    -> email varchar(255)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t_vip(id, name, email) values(1, 'zhangsn', '[email protected]');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(id, name, email) values(2, 'lili', '[email protected]');
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_vip;
+------+---------+----------------+
| id   | name    | email          |
+------+---------+----------------+
|    1 | zhangsn | zhangsn@11.com |
|    2 | lili    | lili@11.com    |
+------+---------+----------------+
2 rows in set (0.00 sec)

# 这里name重复了,会报错
mysql> insert into t_vip(id, name, email) values(3, 'lili', '[email protected]');
ERROR 1062 (23000): Duplicate entry 'lili' for key 'name'
mysql> insert into t_vip(id) values(3);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(id) values(4);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_vip;
+------+---------+----------------+
| id   | name    | email          |
+------+---------+----------------+
|    1 | zhangsn | zhangsn@11.com |
|    2 | lili    | lili@11.com    |
|    3 | NULL    | NULL           |
|    4 | NULL    | NULL           |
+------+---------+----------------+
4 rows in set (0.00 sec)

下面要求name 和 email两个字段联合起来具有唯一性!

先看一个错误示例:

mysql> drop table if exists t_vip;
Query OK, 0 rows affected (0.01 sec)

mysql> create table t_vip(
    -> id int,
    -> name varchar(255) unique,	# 约束直接添加在列后面的,叫做列级约束
    -> email varchar(255) unique
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> insert into t_vip(id,name,email) values(1,'zhangsan','[email protected]');
Query OK, 1 row affected (0.00 sec)
# 下面会报错
mysql> insert into t_vip(id,name,email) values(2,'zhangsan','[email protected]');
ERROR 1062 (23000): Duplicate entry 'zhangsan' for key 'name'

这样创建表示:name具有唯一性,email具有唯一性。各自唯一。

怎样创建这样的表,才能符合新需求呢?

mysql> drop table if exists t_vip;
Query OK, 0 rows affected (0.00 sec)

mysql> create table t_vip(
    -> id int,
    -> name varchar(255),
    -> email varchar(255),
    -> unique(name,email)	# 注意这一句,约束没有添加在列的后面,这种约束被称为表级约束
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t_vip(id,name,email) values(1,'zhangsan','[email protected]');
Query OK, 1 row affected (0.00 sec)
# 并没有报错
mysql> insert into t_vip(id,name,email) values(2,'zhangsan','[email protected]');
Query OK, 1 row affected (0.00 sec)
# 这样会报错---联合唯一
mysql> insert into t_vip(id,name,email) values(3,'zhangsan','[email protected]');
ERROR 1062 (23000): Duplicate entry '[email protected]' for key 'name'

mysql> select * from t_vip;
+------+----------+-------------------+
| id   | name     | email             |
+------+----------+-------------------+
|    1 | zhangsan | zhangsan@123.com  |
|    2 | zhangsan | zhangsan@sina.com |
+------+----------+-------------------+
2 rows in set (0.00 sec)

上面的示例,实现了name和email两个字段联合起来唯一。

13.5 unique和not null可以联合吗

mysql> drop table if exists t_vip;
Query OK, 0 rows affected (0.00 sec)

mysql> create table t_vip(
    -> id int,
    -> name varchar(255) not null unique	# 联合起来
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> desc t_vip;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int(11)      | YES  |     | NULL    |       |
| name  | varchar(255) | NO   | PRI | NULL    |       |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

可以看到,在mysql中,如果一个字段同时被not null和unique约束的话,该字段自动变成主键约束(注意!oracle中不一样!)

mysql> insert into t_vip(id,name) values(1,'zhangsan');
Query OK, 1 row affected (0.00 sec)
# ERROR:name不能重复
mysql> insert into t_vip(id,name) values(2,'zhangsan');
ERROR 1062 (23000): Duplicate entry 'zhangsan' for key 'name'
# ERROR:name不能为NULL
mysql> insert into t_vip(id) values(2);
ERROR 1364 (HY000): Field 'name' doesn't have a default value

13.6 主键约束–primary key(★★★★★)

13.6.1 相关术语

  • 主键约束:就是一种约束
  • 主键字段:该字段上添加了主键约束,这样的字段被称为 主键字段
  • 主键值:主键字段中的每一个值都叫做 主键值

13.6.2 什么是主键?有嘛子用

  • 主键值是每一行记录的唯一标识
  • 主键值是每一行记录的身份证号!

任何一张表都应该有主键,没有主键,表是无效的!

主键的特征:not null + unique (主键值不能是NULL,同时也不能重复!)

13.6.3 怎么给一张表添加主键约束呢?

mysql> drop table if exists t_vip;
Query OK, 0 rows affected, 1 warning (0.00 sec)
# 一个字段做主键,叫做单一主键
mysql> create table t_vip(
    -> id int primary key,	# 添加主键
    -> name varchar(255)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t_vip(id, name) values(1, 'zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(id, name) values(2, 'list');
Query OK, 1 row affected (0.00 sec)
# 错误,id不能重复
mysql> insert into t_vip(id, name) values(2, 'wangwa');
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
# 错误:id不能为NULL
mysql> insert into t_vip(name) values('zhangs');
ERROR 1364 (HY000): Field 'id' doesn't have a default value

可以这样添加主键吗?

mysql> drop table if exists t_vip;
Query OK, 0 rows affected (0.01 sec)

mysql> create table t_vip(
    -> id int,
    -> name varchar(255),
    -> primary key(id)		# 看这里,表级约束
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t_vip(id,name) values(1,'zhangsan');
Query OK, 1 row affected (0.00 sec)
# ERROR
mysql> insert into t_vip(id,name) values(1,'lisi');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

13.6.4 表级约束主要是给多个字段联合起来添加约束的吗?

mysql> drop table if exists t_vip;
Query OK, 0 rows affected (0.00 sec)

mysql> create table t_vip(
    -> id int,
    -> name varchar(255),
    -> email varchar(255),
    -> primary key(id, name)	# id和name联合起来做主键,叫做复合主键!
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t_vip(id,name,email) values(1,'zhangsan','[email protected]');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(id,name,email) values(1,'lisi','[email protected]');
Query OK, 1 row affected (0.00 sec)
# ERROR
mysql> insert into t_vip(id,name,email) values(1,'lisi','[email protected]');
ERROR 1062 (23000): Duplicate entry '1-lisi' for key 'PRIMARY

在实际开发中,不建议使用 复合主键。建议使用单一主键!

因为主键值存在的意义就是这行记录的身份证号,只要意义达到即可,单一主键就可以做到。
复合主键比较复杂,不建议使用!!!

13.6.5 一个表中主键约束能加两个吗?

mysql> create table t_vip(
    -> id int primary key,
    -> name varchar(255) primary key
    -> );
ERROR 1068 (42000): Multiple primary key defined

结论:一张表,主键约束只能添加1个(主键只能有1个,当然可以有复合主键)

13.6.6 auto_increment机制

在mysql中,auto_increment 机制可以帮助我们自动维护一个主键值:

mysql> drop table if exists t_vip;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create table t_vip(
    -> id int primary key auto_increment,	# auto_increment表示自增,从1开始,以1递增!
    -> name varchar(255)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t_vip(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_vip;
+----+----------+
| id | name     |
+----+----------+
|  1 | zhangsan |
|  2 | zhangsan |
|  3 | zhangsan |
|  4 | zhangsan |
|  5 | zhangsan |
+----+----------+
5 rows in set (0.00 sec)

13.6.7 建议

主键值建议使用:

  • int、bigint、char等类型

不建议使用 varchar 来做主键。

主键值一般都是数字------一般都是定长的。

主键除了:单一主键 和 复合主键,还可以这样分类:

  • 自然主键:主键值是一个自然数,和业务没关系
  • 业务主键:主键值和业务紧密关联
    例如:拿银行卡账号做主键值,这就是业务主键!

在实际开发中,自然主键使用比较多,因为主键只要做到不重复就行,不需要有意义。业务主键不好,因为主键一旦和业务挂钩,那么当业务发生变动的时候,可能会影响到主键值,所以业务主键不建议使用。

13.7 外键约束–foreign key(★★★★★)

外键约束相关术语:

  • 外键约束:一种约束
  • 外键字段:添加了外键约束的字段
  • 外键值:外键字段当中的每一个值

业务背景:

请设计数据库表,来描述“班级和学生”的信息?

第一种方案:班级和学生存储在一张表中:

t_student
no(pk)			name		classno			classname
----------------------------------------------------------------------------------
1					jack			100			北京市大兴区亦庄镇第二中学高三12					lucy			100			北京市大兴区亦庄镇第二中学高三13					lilei			100			北京市大兴区亦庄镇第二中学高三14					hanmeimei		100			北京市大兴区亦庄镇第二中学高三15					zhangsan		101			北京市大兴区亦庄镇第二中学高三26					lisi			101			北京市大兴区亦庄镇第二中学高三27					wangwu			101			北京市大兴区亦庄镇第二中学高三28					zhaoliu			101			北京市大兴区亦庄镇第二中学高三2

方案缺点:

  • 数据冗余,空间浪费

第二种方案:班级一张表、学生一张表:

t_class 班级表
classno(pk)			classname
------------------------------------------------------
100					北京市大兴区亦庄镇第二中学高三1101					北京市大兴区亦庄镇第二中学高三1班
	
t_student 学生表
no(pk)				name				cno(FK引用t_class这张表的classno)
----------------------------------------------------------------
1					jack				100
2					lucy				100
3					lilei				100
4					hanmeimei			100
5					zhangsan			101
6					lisi				101
7					wangwu				101
8					zhaoliu				101

注意:t_class是父表,t_student是子表
删除表的顺序 ===》 先删子,再删父
创建表的顺序 ===》 先创建父,再创建子
删除数据的顺序 ===》 先删子,再删父
插入数据的顺序 ===》 先插入父,再插入子

当cno字段没有任何约束的时候,可能会导致数据无效。如可能出现一个102班级,但是102班级并不存在,所以为了保证cno字段中的值都是100和101,需要给cno字段添加外键约束

===》cno字段就是外键字段,cno字段中的每个值都是外键值

思考:子表中的外键引用的父表中某个字段,被引用的这个字段必须是主键吗?

===》不一定是主键,但至少具有unique约束

测试:外键可以为NULL吗?

===》外键值可以是NULL

猜你喜欢

转载自blog.csdn.net/qq_45893475/article/details/121317415