Mysql中的约束

约束(constraint)

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

约束分类

非空约束:not null

  • 非空约束,针对某个字段设置其值不为空

唯一性约束: unique

  • 唯一性约束,它可以使某个字段的值不能重复 , 如果没有指定 not null , 则 unique 字段可以有多个 null , 因为null不是具体的值 , 所以不算重复
  • 一张表可以有多个 unique 字段

主键约束: primary key (简称PK)

外键约束:foreign key(简称FK)

检查约束:check(不建议使用 , mysql不支持,oracle支持)

表级约束和列级约束

约束直接添加到列后面的叫做列级约束 , 直接在字段名后指定: 字段名 约束名

  • 列级约束主要是给一个字段添加某一个约束
create table t_vip(
	id int,
    --not null只有列级约束,没有表级约束
	name varchar(255) not null
);

约束直接在在表定义的最后添加的约束被称为表级约束: 约束名(列名1…)

  • 表级约束主要是给多个字段联合起来添加某一个约束(也可以是一个字段)
  • not null只有列级约束,没有表级约束
create table t_vip(
    id int,
    name varchar(255),
    email varchar(255),
    --约束没有添加在列的后面,这种约束被称为表级约束
    unique(name,email) 
);

not null约束

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zdwOksyy-1676261205990)(C:\Users\meng\AppData\Roaming\Typora\typora-user-images\1666962353865.png)]

测试非空约束

drop table if exists t_vip;
	create table t_vip(
		id int,
        --not null只有列级约束,没有表级约束
		name varchar(255) not null
	);
	insert into t_vip(id,name) values(1,'zhangsan');
	insert into t_vip(id,name) values(2,'lisi');

	--ERROR 1364 (HY000): Field 'name' doesn't have a default value
	insert into t_vip(id) values(3);

unique约束

一张表可以有多个 unique 字段 , 另外被unique约束的字段如果没有指定 not null约束 , 则可以插入多个NULL不算重复(null不是具体的值)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oyDlCiDC-1676261205991)(C:\Users\meng\AppData\Roaming\Typora\typora-user-images\1666962372902.png)]

测试唯一约束

	drop table if exists t_vip;
	create table t_vip(
        id int,
        name varchar(255) unique,
        email varchar(255)
    );
    
	insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
	insert into t_vip(id,name,email) values(2,'lisi','lisi@123.com');
	insert into t_vip(id,name,email) values(3,'wangwu','wangwu@123.com');
	
	--	ERROR 1062 (23000): Duplicate entry 'wangwu' for key 'name'
	insert into t_vip(id,name,email) values(4,'wangwu','wangwu@sina.com');

	--name字段虽然被unique约束了,但是可以为NULL
	--如果没有指定 not null , 则unique字段可以有多个null不算重复
	insert into t_vip(id) values(4);
	insert into t_vip(id) values(5);

unique 和 not null 联合使用

在mysql当中,如果一个字段同时被not null和unique约束的话,该字段自动变成主键字段 , 但是Oracle中不一样

create table t_vip(
	id int,
	name varchar(255) not null unique
);

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

两个字段具有各自唯一性

--这样创建表示:name具有唯一性,email具有唯一性
create table t_vip(
    id int,
    name varchar(255) unique, 
    email varchar(255) unique
);

insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@sina.com');

--ERROR 1062 (23000): Duplicate entry 'zhangsan-zhangsan@sina.com' for key 'name'	
insert into t_vip(id,name,email) values(2,'zhangsan','zhangsan@sina.com');

两个字段联合起来具有唯一性

create table t_vip(
    id int,
    name varchar(255),
    email varchar(255),
    --约束没有添加在列的后面,这种约束被称为表级约束
    unique(name,email) 
);
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(2,'zhangsan','zhangsan@sina.com');

--ERROR 1062 (23000): Duplicate entry 'zhangsan-zhangsan@sina.com' for key 'name'	
insert into t_vip(id,name,email) values(3,'zhangsan','zhangsan@sina.com');

主键约束primary key

主键的相关术语

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

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

  • 主键值是每一行记录的唯一标识 (身份证号) , 主键值一般都是数字,一般都是定长的, 建议使用:int , bigint , char等类型 , 不建议使用:varchar来做主键
  • 任何一张表都应该有主键,没有主键则表无效

在这里插入图片描述

主键分为单一主键和复合(联合)主键,单一主键是由一个字段构成的,复合(联合)主键是由多个字段构成的 , 实际开发中建议使用单一主键

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

主键除了单一主键和复合主键之外,还可以分为自然主键和业务主键

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

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

一张表主键约束只能有一个 , 但是这个主键可以是单一主键也可以是复合主键

  • 复合主键是给多个字段联合添加一个主键约束, 本质就是一个主键
--ERROR 1068 (42000): Multiple primary key defined
create table t_vip(
	id int primary key,
	name varchar(255) primary key
);

使用列级约束添加单一主键

--1个字段做主键,叫做:单一主键
--使用列级约束添加主键
create table t_vip(
    --表示id列是主键
	id int primary key, 
	name varchar(255)
);
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi');

--错误不能重复: ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
insert into t_vip(id,name) values(2,'wangwu');

--错误不能为NULL: ERROR 1364 (HY000): Field 'id' doesn't have a default value
insert into t_vip(name) values('zhaoliu');		

使用表级约束添加单一主键

--使用表级约束添加单一主键
create table t_vip(
	id int,
	name varchar(255),
	primary key(id)  
);

使用表级约束添加复合主键

--使用表级约束给多个字段联合起来添加主键约束: 复合主键
create table t_vip(
	id int,
    name varchar(255),
    email varchar(255),
    primary key(id,name)
 );
 
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(1,'lisi','lisi@123.com');

--错误不能重复: ERROR 1062 (23000): Duplicate entry '1-lisi' for key 'PRIMARY'
insert into t_vip(id,name,email) values(1,'lisi','lisi@123.com');

auto_increment

在MySql当中的自动维护一个主键值的机制: auto_increment表示自增 , 从1开始,以1递增

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zvVS1meQ-1676261205992)(C:\Users\meng\AppData\Roaming\Typora\typora-user-images\1666963230079.png)]

在这里插入图片描述

drop table if exists t_vip;
create table t_vip(
--auto_increment表示自增,从1开始,以1递增
id int primary key auto_increment,
name varchar(255)
);

--添加自增长的字段的三种方式
insert into t_vip(id,name) values(null,'zhangsan');
--推荐使用这种方式
insert into t_vip(name) values('zhangsan');
insert into t_vip values(null,'zhangsan');

-- 修改默认的自增长开始值
ALTER TABLE t25 AUTO_INCREMENT = 100

外键约束

外键主要是维护表之间的关系的,主要是为了保证参照完整性,如果表中的某个字段为外键字段,那么该字段的值必须来源于所参照的表的主键

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N8RkMB8f-1676261205993)(C:\Users\meng\AppData\Roaming\Typora\typora-user-images\1666963659328.png)]

在这里插入图片描述

外键约束涉及到的相关术语

  • 外键约束:一种约束(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

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

  • 子表中的外键引用的父表中的某个字段,被引用的这个字段不一定是主键,但至少具有unique约束 , 外键值可以为NULL
		--t_class 主表(班级表)
		classno(pk)			classname
		------------------------------------------------------
		100					北京市大兴区亦庄镇第二中学高三1101					北京市大兴区亦庄镇第二中学高三1--t_student 从表(学生表)
		--当cno字段没有任何约束的时候,可能会导致数据无效。可能出现一个102,但是102班级不存在,所以为了保证cno字段中的值都是100和101,需要给cno字		  段添加外键约束,那么:cno字段就是外键字段。cno字段中的每一个值都是外键值
		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_classes
drop table if exists t_classes;
create table t_classes(
    classes_id int(3) primary key,
    classes_name varchar(40),
)

--建立t_student 并加入外键约束
drop table if exists t_student;
create table t_student(
    student_id int(10) primary key auto_increment,
    student_name varchar(20),
    sex char(2),
    birthday date,
    email varchar(30),
    --外键值可以为NULL,成功的插入了学生信息,但是 classes_id 没有值,这样会影响参照完整性,所以我们建议将外键字段设置为非空
    --不确定外键的情况下可以使用NULL
    classes_id int(3) not null,
    foreign key(classes_id) references t_classes(classes_id)
    --constraint student_id_pk primary key(student_id),
    --constraint fk_classes_id foreign key(classes_id) references t_classes(classes_id) 
)

--向 t_student 中加入数据
--出现错误,因为在班级表中不存在班级编号为 10 班级,外键约束起到了作用存在外键的表就是子表,参照的表就是父表,所以存在一个父子关系,也就是主从关系,主表就是班级表,从表就是学生表
insert into t_student(student_id, student_name, sex, birthday, email, classes_id) values(1001, 'zhangsan', 'm', '1988-01-01', 'qqq@163.com', 10)

--外键值可以为NULL,成功的插入了学生信息,但是 classes_id 没有值,这样会影响参照完整性,所以我们建议将外键字段设置为非空
insert into t_student(student_id, student_name, sex, birthday, email, classes_id) values(1001, 'zhangsan', 'm', '1988-01-01', 'qqq@163.com', NULL)

添加数据到班级表,添加数据到学生表,删除班级数据,将会出现如下错误

t_classes是父表 , t_student是子表

  • 删除表的顺序: 先删子,再删父
  • 创建表的顺序: 先创建父,再创建子
  • 删除数据的顺序: 先删子,再删父
  • 插入数据的顺序: 先插入父,再插入子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WfVErX24-1676261205993)(C:\Users\meng\AppData\Roaming\Typora\typora-user-images\1666948933836.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s2HUlGMT-1676261205994)(C:\Users\meng\AppData\Roaming\Typora\typora-user-images\1666949007518.png)]

--插入数据的顺序: 先插入父,再插入子
insert into t_classes (classes_id,classes_name) values (10,'366');

insert into t_student(student_id, student_name, sex, birthday, email, classes_id) 
values(1001, 'zhangsan', 'm', '1988-01-01', 'qqq@163.com', 10)

因为子表(t_student)存在一个外键 classes_id,它参照了父表(t_classes)中的主键,所以先删除子表中的引用记录,再修改父表中的数据
update t_classes set classes_id = 20 where classes_name = '366';

delete from t_classes where classes_id = 10;

因为子表(t_student)存在一个外键 classes_id,它参照了父表(t_classes)中的主键,所以
先删除父表,那么将会影响子表的参照完整性,所以正确的做法是,先删除子表中的数据,
再删除父表中的数据,采用 drop table 也不行,必须先 drop 子表,再 drop 父表


check约束

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2E92Zf5u-1676261205994)(C:\Users\meng\AppData\Roaming\Typora\typora-user-images\1666964458222.png)]

CREATE TABLE t23 (
	id INT PRIMARY KEY, 
    `name` VARCHAR(32) , 
    sex VARCHAR(6) CHECK (sex IN('man','woman')), 
    sal DOUBLE CHECK ( sal > 1000 AND sal 	< 2000)
); 

--mysql5.7目前还不支持check,只做语法校验所以约束不会生效,数据依旧能插入表中
INSERT INTO t23
VALUES(1, 'jack', 'mid', 1);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值