问: 约束存在的意义是什么?
答:为防止错误的数据被插入到数据表,MySQL中定义了一些维护数据库完整性的规则;这些规则常称为表的约束 是对数据准确性的一种提前控制
例如:人员的姓名不能为空,人的年龄只能在0~150岁之间。约束可以对数据库中的数据进行保护。
约束可以在建表的时候直接声明,也可以为已建好的表添加约束。
我们简单说一下约束的几种类型和使用方法

这个算是我们最常使用的 我们在创建表的时候一般会选用ID做主键约束 主键约束用于唯一的标识表中的每一行。被标识为主键的数据在表中是唯一的且其值不能为空。这点类似于我们每个人都有一个身份证号,并且这个身份证号唯一,也就是我们的ID 全部都是不能重复 也就衍生出很多 主键的生成策略 UUID 雪花算法等等
问: 如果我们在创建的时候没有去主动设置一个主键约束怎么办?MySQL数据表使用InnoDB作为存储引擎的时候,数据结构就是使用B+树,而数据本身存储在主键索引上,也就是通常所说的聚簇索引,也就是每个表都需要有个聚簇索引树,但是,在建表的时候却发现可以不用指定主键,那么MySQL对于没有指定主键的表示如何处理的呢?
回答:
既然InnoDB对数据的存储必须依赖于主键,那么对于没有创建主键的表,该怎么办?
InnoDB对聚簇索引处理如下:
很明显,缺少主键的表,InnoDB会内置一列用于聚簇索引来组织数据。而没有建立主键的话就没法通过主键来进行索引,查询的时候都是全表扫描,小数据量没问题,大数据量就会出现性能问题。
但是,问题真的只是查询影响吗?不是的,对于生成的ROW_ID,其自增的实现来源于一个全局的序列,而所以有ROW_ID的表共享该序列,这也意味着插入的时候生成需要共享一个序列,那么高并发插入的时候为了保持唯一性就避免不了锁的竞争,进而影响性能。
即便我们没有去主动创建一个主键约束 MySQL 数据库也会创建帮我们去创建一个
如果定义了主键,那么InnoDB会使用主键作为聚簇索引
如果没有定义主键,那么会使用第一非空的唯一索引(NOT NULL and UNIQUE INDEX)作为聚簇索引
如果既没有主键也找不到合适的非空索引,那么InnoDB会自动生成一个不可见的名为row_id的列名为GEN_CLUST_INDEX的聚簇索引,该列是一个6字节的自增数值,随着插入而自增–补充:该全局row_id在代码实现上使用的是bigint unsigned类型,但实际上只给row_id留了6字节,这种设计就会存在一个问题:如果全局row_id一直涨,一直涨,直到2的48幂次-1时,这个时候再+1,row_id的低48位都为0,结果在插入新一行数据时,拿到的row_id就为0,存在主键冲突的可能性
自动生成的主键约束会有什么问题?
1、通过创建表的时候创建
CREATE TABLE test (
//这个id 就是主键约束
id int PRIMARY key
)
2、通过语法去创建
alter table 表名 modify 列名 数据类型 primary key;
主键约束相当于唯一性约束+ 非空约束,主键约束不允许重复,也不允许出现空值
一个表最多只能有一个主键约束,建立主键约束可以在列级别创建,也可以在表级别创建
上面那说到 主键约束 就等于 唯一性约束 + 非空约束 非空约束也就是 这个值不能为空 如果出现空值就会出现报错
1、作用:限定某个字段/某列的值不允许为空
2、关键值:no null
3、特点:
创建数据表时:
CREATE TABLE test(name varchar(20) not null);
创建数据表后:
alter table 表名称 modify 字段名 数据类型 not null;(模板)
例子:alter table test modify name varchar(20) not null;
create table 表名称(
字段名1 数据类型 primary key,
字段名2 数据类型 【unique key】【not null】 default 默认值,
字段名3 数据类型 default 默认值,
。。。。
);
例如:
create table student(
sid int primary key,
sname varchar(20) not null,
gender char default '男'
);
insert into student values(1,'变成派大星');
ERROR 1136 (21S01): Column count doesn't match value count at row 1 ' 列数与值数量
不匹配
insert into student values(1,'变成派大星',default);
insert into student(sid,sname) values(2,'海绵宝宝');
alter table [数据库名.]表名称 modify 字段名 数据类型 default 默认值;
create table student(
sid int primary key,
sname varchar(20) not null,
gender char
);
alter table student modify gender char default '男';
提醒:如果某个字段既要非空,又要默认值,那么alter 语句后面两个都要写。
create table student(
sid int primary key,
sname varchar(20) not null,
gender char not null
);
增加gender还有默认值
alter table student modify gender char default '男' not null;
alter table [数据库名]表名称 modify 字段名 数据类型 [not nul]; #不写默认值约束
insert into t_stu values (1,'变成派大星','未知');
update t_stu set gender = default where sid = 1;
唯一约束用来保证一列(或一组列)中的数据是唯一的。类似与主键,但是有以下区别:
1、通过创建表的时候创建
CREATE TABLE test (
id int PRIMARY key auto_increment,
// 创建唯一约束
name VARCHAR(20) UNIQUE
)
2、通过命令创建唯一约束
ALTER TABLE 表名
ADD CONSTRAINT 索引名称 UNIQUE (列名);
-- 在已创建好的表上加唯一约束,指定约束名为name
ALTER TABLE student
ADD CONSTRAINT um UNIQUE (name);
-- 在已创建好的表上加唯一约束,不指定约束名
ALTER TABLE student
ADD UNIQUE (name);
创建多个唯一索引
ALTER TABLE student
ADD CONSTRAINT un UNIQUE (name,age
);
3、删除唯一约束
查询索引
SHOW INDEX FROM 表名;
删除索引
-- 格式一:
DROP INDEX 约束名 ON 表名;
-- 例如:
DROP INDEX name ON student;
-- 格式二:
ALTER TABLE 表名
DROP INDEX 约束名;
-- 例如:
ALTER TABLE student
DROP INDEX name;
1、特点 如果数据表含有从属关系,比如部门和员工, 教室和桌椅,班级和同学就可以使用一对多的制表关系 一的一方定义为主表, 多的一方定义为从表 在多的一方添加一列,作为外键约束 ,引用少的一方的主键 如果主表中的主键被应用,则该条数据无法被删除 如果从表中的外键找不到相同值的主键,则无法被插入
CREATE TABLE category
(
cid VARCHAR(32) PRIMARY KEY,
cname VARCHAR(100)#分类名称
);
# 商品表
# 外键约束的添加格式
# 在创建时在最下方添加外键约束:constraint(约束) foreign key(外键字段) reference(参考) 主表(主键)
CREATE TABLE products
(
pid VARCHAR(32) PRIMARY KEY,
name VARCHAR(40),
price DOUBLE,
category_id VARCHAR(32),
CONSTRAINT FOREIGN KEY (category_id) REFERENCES category1 (cid) # 添加约束
);
不过现在外键索引用的比较少还是看个人使用
1、主键约束
主键是表中能唯一识别表中每条信息的字段。要求:唯一、非空。一个表中只能有1个主键。
2、外键约束
与主键结合使用,确保数据的一致性。
3、唯一约束
一个表中可以有多个字段设置唯一约束,允许存在空值。
4、检查约束
用来检查数据表中,字段值是否有效,减少无效数据的输入。
5、非空约束
设置了非空约束的字段,不允许出现空值。
6、默认值约束
设置了默认值约束的字段,在该字段无数据输入时,会自动添加一个默认值。通常和非空约束一起使用。
不论是单字段主键还是多字段联合主键都需要满足:
主键能唯一标识表中每一行数据,且一个表中只能有1个主键的唯一性;
主键不能有NULL值;
联合主键中字段名不能重复出现。
1、 CREATE TABLE 语句中
单字段主键在定义字段时,创建约束
CERATE TABLE <表名> (<字段名> <数据类型> PRIMARY KEY [默认值],...)
2、命令创建
CERATE TABLE <表名> (<字段名> <数据类型> ,...,[CONSTRAINT <约束名>] PRIMARY KEY [字段名])
3、 多字段联合主键:
CERATE TABLE <表名> (<字段名> <数据类型> ,...,PRIMARY KEY [字段1,字段2,…,字段n])
4、 ALTER TABLE 语句中修改约束:
ALTER TABLE <表名> ADD PRIMARY KEY(<字段名>);
5、 删除约束:
ALTER TABLE <表名> DROP PRIMARY KEY;
外键是与主键一起使用的,用来约束两个表的数据一致性和完整性。主键所在表为主表,外键所在表为从表。
1、外键需遵守的规则
一个表可以有多个外键,允许有空值;
主表已存在于数据库中,或为正创建的表。主表必须已指定主键;
外键中字段数目、对应的字段数据类型必须与主键中字段数目、对应的字段数据类型相同。
1、CREATE TABLE 语句中,
CERATE TABLE <表名> (<字段名> <数据类型> ,...,[CONSTRAINT <外键名>] FOREIGN KEY 字段名 [,字段名2,…]
REFERENCES <主表名> 主键列1 [,主键列2,…])
复制代码
2、 命令创建
2.1、修改外键约束:
ALTER TABLE <表名> ADD CONSTRAINT <外键名>
FOREIGN KEY(<列名>) REFERENCES <主表名> (<列名>);
2.2、 删除外键约束:
ALTER TABLE <表名> DROP FOREIGN KEY <外键约束名>;
复制代码
设置唯一约束的语法格式:
1、 CREATE TABLE 语句中,
CERATE TABLE <表名> (<字段名> <数据类型> UNIQUE,...);
2、ALTER TABLE 语句中,
2.1 修改唯一约束:
ALTER TABLE <表名> ADD CONSTRAINT <唯一约束名> UNIQUE(<列名>);
2.2 删除唯一约束:
ALTER TABLE <表名> DROP INDEX <唯一约束名>;
设置检查约束的语法格式:
1、 CREATE TABLE 语句中,
CERATE TABLE <表名> (<字段名> <数据类型> ,...,CHECK <检查约束>);
<检查约束>,可以是简单的表达式,也可以是子查询
2、ALTER TABLE 语句中,
2.1 修改检查约束:
ALTER TABLE <表名> ADD CONSTRAINT <检查约束名> CHECK(<检查约束>);
2.2 删除检查约束:
ALTER TABLE <表名> DROP CONSTRAINT <检查约束名>;
设置默认值的语法格式:
1、CREATE TABLE 语句中,
CERATE TABLE <表名> (<字段名> <数据类型> DEFAULT <默认值>,...);
2、ALTER TABLE 语句中,
2.1 修改默认值:
ALTER TABLE <表名>
CHANGE COLUMN <字段名> <数据类型> DEFAULT <默认值>;
2.2 删除默认值:
ALTER TABLE <表名>
CHANGE COLUMN <字段名> <字段名> <数据类型> DEFAULT NULL;
设置非空约束的语法格式:
1、CREATE TABLE 语句中,
CERATE TABLE <表名> (<字段名> <数据类型> NOT NULL,...);
2、ALTER TABLE 语句中,
2.1 修改非空约束:
ALTER TABLE <表名> CHANGE COLUMN <字段名>
<字段名> <数据类型> NOT NULL;
2.2 删除非空约束:
ALTER TABLE <表名> CHANGE COLUMN <字段名>
<字段名> <数据类型> NULL;