数据库约束

何为约束,根据表的数据内容作出限制,在创建表的时候,确定出来,跟随建表语句,一起设置到数据库服务器中。

1.约束类型:

NOT NULL - 指示某列不能存储 NULL 值。
UNIQUE - 保证某列的每行必须有唯一的值。
DEFAULT - 规定没有给列赋值时的默认值。
PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标
识,有助于更容易更快速地找到表中的一个特定的记录。
FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性。
CHECK - 保证列中的值符合指定的条件。对于MySQL数据库,对CHECK子句进行分析,但是忽略
CHECK子句。

1.1:NOT NULL,UNIQUE,DEFAULT

注意:a.default是Mysql设定的默认值,不需要我们去单独设定;

b.指定列插入时,未指定值是就是默认值default;

c.对于空值null插入时,当插入行是unique,null值不视为重复;

2.主键约束(PRIMARY KEY):

主键约束是数据的一条身份标识,它相当于NOT NULL + UNIQUE;

2.1.语法:

sql 复制代码
create table student(id int primary key,sn int unique,name varchar(20),qq_email varchar(20));

**注意:**a.如图所示,在Mysql中,unique+not null会被自动转换成primary key;

b.一个表中,只能有一个主键,但一个主键可以包含多个列,这样即构成了联合主键(不建议使用);

2.2自增主键:

自增主键就是给主键字段按顺序生成唯一数字,不需要手动赋值,保证主键不重复,不混乱;

注意:a.只有主键或者唯一键才能用自增操作;

b.必须为数值类型,如int bigint;

c.即使不指定id,Mysql也会根据自增主键自动添加编号;

d.如果中间出现不连续的数据,编译器会根据最后插入的数据进行自增,例如当我在插入id=3的数据后,再偷偷插入id=100,自增主键会根据我最后插入的100进行自增;

**【疑问】:**当数据库被做成分布式的,那么数据库或数据表可能被拆成很多份,分别存储在多个Mysql的机器上,那么此时自增主键无法确保两个机器上的数据都还是唯一的,这是我们应该怎么做?

【解答】:这里我们给出一种方式,雪花算法,这种方式企业常用,保证全局唯一、趋势递增、高性能、无中间件依赖,是分布式系统首选的主键方案;

a.目的:在分布式的环境下,快速生成唯一 ,有序 ,纯数字的ID;

b. 特点:1).生成64位long类型数据;

2).全局唯一;

3).趋势递增,Mysql主键友好;

4).高并发:每秒生成百万级ID。

c.ID结构:一个雪花ID = 64个二进制位

= 一位符号位 + 41位时间戳 + 10位机器ID + 12位序列号;

注意:1).符号位:这里的符号位固定为0(表示ID永远为正数);

2).41位时间戳:单位毫秒,从某个时间开始算,能用69年,保证ID趋势递增;

3).机器ID:例如可以为 5位数据中心 ID +5 位机器 ID ;

4).12位序列号:同一毫秒,同一台机器内生成的自增序号,从0开始,到4095,每毫秒最多生 成4096个ID ,保证高并发下不重复;

d.核心原理:同一毫秒 + 同一机器 + 唯一序列号 = 绝对唯一 ID;

e.流程:

  • 获取当前毫秒时间戳
  • 如果是同一毫秒,序列号 + 1
  • 如果序列号用完(4095),等待到下一毫秒
  • 把 符号位 + 时间戳 + 机器 ID + 序列号 拼接成一个数字

3.外键约束(FOREIGN KEY):

用于建立两个表中的关联关系,让一个表的字段引用另一个表的主键,保证数据的完整性,一致性,防止无效数据。

简单来说就是 子表的外键 = 父表的主键,子表不能插入父表中不存在的数据。

3.1语法:

sql 复制代码
CREATE TABLE 子表 (
    字段名 类型,
    FOREIGN KEY (子表字段) REFERENCES 父表(主键)
);

举例:

sql 复制代码
-- 父表创建:
drop table if exists student;
create TABLE classes(id int primary key auto_increment,name varchar(20),`desc` varchar(20));
-- 子表创建:
drop table if exists classes;
create table student(id int primary key auto_increment,name varchar(20) default 'ubknown',qq_email varchar(20),classes_id int,foreign key(classes_id) references classes(id));

3.2:修改数据是否可行?

那么是否可以从父表或者子表修改这两个表的数据呢?答案肯定是不行的,来看上面编译器运行代码的两个报错,核心意思就是外键约束失败,当你想删除/更新父/子表时,另外一个表中仍然有数据在引用他,数据库为了保护数据不混乱,禁止你删除!

sql 复制代码
-- 父表创建:
drop table if exists student;
create table classes(class_id int primary key auto_increment,class_name varchar(20) default "inknown");
desc student;
-- 子表创建:
drop table if exists classes;
create table student(id int primary key auto_increment,name varchar(20) default 'ubknown',classes_id int,foreign key(classes_id) references classes(class_id));
desc classes;
insert into classes values(null,"java101"),(null,"java102"),(null,"java103");
select * from classes;
insert into student values(null,"张三",1),(null,"李四",2),(null,"王五",3);
insert into student values(null,"赵六",2);
select *from student;
update student set classes_id=100 where id=1;
delete from classes where class_id=1;

3.3:经典面试题:

这里有一个场景,在一个电商网站,存在两张表,一张商品表(父表),一张订单表(子表),那么如果商家想进行商品信息更改,根据前面的知识,肯定不能直接对子表或者父表进行修改,也就是说不能进行物理意义在硬盘上删除,那么此时我们就可以在创建父表时在数据栏加上一列isOk,他表示逻辑删除,1代表存在,0代表已删除,这样就可以解决这个问题了。

4.CHECK约束:

指定一个条件,根据实际需求,灵活定义,check内部可以写各种条件,check从MYSQL8才开始支持,虽然MYSQL5.7使用不会报错,但没有实际效果!

4.1列级约束:创建表时,字段后直接写

sql 复制代码
CREATE TABLE student (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(20),
  age INT CHECK (age >= 0),          -- 年龄不能小于0
  gender CHAR(2) CHECK (gender IN ('男','女')),  -- 性别只能男女
  score INT CHECK (score BETWEEN 0 AND 100)      -- 分数0-100
);

4.2表级约束:创建表时,最后统一写

sql 复制代码
CREATE TABLE student (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(20),
  age INT,
  score INT,
  -- 统一写 CHECK
  CHECK (age >= 0),
  CHECK (score BETWEEN 0 AND 100)
);

4.3:报错:

违反check会出现这个报错,3819 - Check constraint 'student_chk_1' is violated.原因是插入的值不满足约束条件,数据库拒绝!

本章完。。。。。。

相关推荐
Greyson120 分钟前
Layui表格如何使用第三方插件实现树形展示.txt
jvm·数据库·python
2401_8716965231 分钟前
mysql行级锁失效的原因排查_检查查询条件与执行计划
jvm·数据库·python
Elastic 中国社区官方博客1 小时前
Elasticsearch:快速近似 ES|QL - 第一部分
大数据·运维·数据库·elasticsearch·搜索引擎·全文检索
Dontla1 小时前
高基数(High Cardinality)问题介绍(Prometheus、高基数字段、低基数字段)
前端·数据库·prometheus
a9511416421 小时前
CSS如何实现元素隐藏不占位_使用display-none完全移除
jvm·数据库·python
SelectDB技术团队2 小时前
SelectDB Enterprise 4.0.5:强化安全与治理,构建企业级实时分析与 AI 数据底座
数据库·人工智能·apache doris
一 乐2 小时前
医院挂号|基于springboot + vue医院挂号管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·医院挂号管理系统
ego.iblacat3 小时前
Redis 核心概念与部署
数据库·redis·缓存
m0_493934533 小时前
如何监控AWR数据收集Job_DBA_SCHEDULER_JOBS中的BSLN_MAINTAIN_STATS
jvm·数据库·python
万岳科技系统开发3 小时前
商城系统搭建自建平台与入驻第三方平台对比分析
数据库·小程序·架构