数据库约束

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

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.原因是插入的值不满足约束条件,数据库拒绝!

本章完。。。。。。

相关推荐
卷Java2 小时前
Python字典:键值对、get()方法、defaultdict,附通讯录实战
开发语言·数据库·python
wanhengidc2 小时前
跨境云手机适用于哪些场景
大数据·运维·服务器·数据库·科技·智能手机
Bdygsl2 小时前
MySQL(6)—— 视图
数据库·mysql
oradh2 小时前
数据库入门概述
数据库·oracle·数据库基础·数据库入门
BullSmall3 小时前
一套定制化高级 payload 合集
数据库·安全性测试
zbdx不知名菜鸡3 小时前
postgre sql 数据库查询优化
数据库·postgresql
9稳3 小时前
基于PLC的生产线自动升降机设计
开发语言·网络·数据库·嵌入式硬件·plc
四七伵3 小时前
Spring Boot项目中varchar字段为什么不用NULL?告别空指针从建表开始
数据库·后端
Mr.45673 小时前
JDK17+Druid+SpringBoot3+ShardingSphere5 多表分库分表完整实践(MySQL+PostgreSQL)
java·数据库·spring boot·mysql·postgresql