约束的必要性
先进行讨论约束的必要性,只有知道约束的必要性我们才能每个约束条件存在的意义。
在前面我们进行介绍过数据类型可以进行约束,但是仅仅依靠数据类型进行约束,非常单一,还是会出现各种各样的问题,例如,将手机号和身份证号的信息进行填写反了等等问题,这种情况仅仅依靠数据类型来进行约束是不可取的。
用户的数据通过网络传输,序列化、反序列化等等操作然后将数据进行插入到数据库中,数据库是维护用户数据的最后一道防线,我们需要确保数据的合法性,就像我们进行编写程序的编译器那样,这样是实现要求还需要其他的约束条件。
非空约束
在进行创建表的时候可以进行设置表中的字段是否可以为空。
数据库中默认字段一般都是可以为NULL的,但是实际开发中很多场景是不可以为空的,例如我们在进行创建账号的时候,必须进行输入昵称,如果昵称没有进行输入就不可以进行创建账号,相反一般个人简介可以不进行设置,也允许我们进行创建;
上面的现象是如何做到的呢?这就是使用了非空约束。
再比如我们的大学生活每天都奔波于课程,每个课程对应的教室是不同的,如果只有课程名称,没有进行设置对应的教室的时候我们也无法进行正常上课,反之亦是。
当我们进行插入时,由于设置不能为null,所以进行插入时必须要在设置成not null 进行插入数据,由于other是null的,所以既可以进行插入也可以不插入。
default约束
default 翻译成中文是默认值,当我们没有进行显示调用时会采用默认的值进行填充。
mysql语法是允许我们进行将default 和not null 进行同时设置的,但是我们在进行实际开发中是很少进行一起使用的。
约束组合 | 含义说明 | 示例 | 插入行为(未显式指定该字段) |
---|---|---|---|
NULL (默认值未指定) |
字段允许为 NULL ,未指定值时插入 NULL |
age INT NULL |
插入为 NULL |
NULL DEFAULT <值> |
字段允许为 NULL ,但未赋值时使用默认值(不是 NULL) |
status INT NULL DEFAULT 1 |
插入为默认值 1 |
NOT NULL (默认值未指定) |
字段必须赋值,插入时若不提供值会报错 | name VARCHAR(10) NOT NULL |
未赋值时报错 |
NOT NULL DEFAULT <值> |
字段不允许为 NULL ,若未赋值则使用默认值 |
score INT NOT NULL DEFAULT 100 |
插入时未赋值则使用默认值 100 |
NOT NULL DEFAULT NULL (非法) |
与逻辑冲突,部分数据库不允许 | ❌ | 报错(MySQL 8.0 不允许) |
列描述约束
comment:翻译成中文的含义是描述,列描述其实是一种软描述(只是进行增添注释进行提醒约束)
zerofill
zero这种约束是一种主动约束,为了进行统一格式。
当数据的位数没有满足统一的格式时,进行补0进行填充
当数据的位数超过统一的格式时,此时不进行发生变化。
主键
主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键;主键 所在的列通常是整数类型。
mysql保证主键必须唯一,也就是说被设置成主键的列不能出现重复的
当一张表进行创建出来但是没有将某一列设为主键,也就是说此事这张表中没有主键,可以进行追加主键
alter table 表名 add primary key(字段列表)
进行设置主键时,如果设置主键的那一列存在重复的,则无法进行追加主键。
删除主键
alter table 表名 drop primary key;
复合主键
在前面进行介绍主键的时候,明明说过一张表中的主键只能有一个,为什么存在复合主键,通过查看表结构发现表中存在两个主键了是什么情况?
其实是order_id + product_id 联合作为主键,这相当于一个键值对作为一个主键,并不是每个作为一个主键,确保一张订单中每种商品只出现一次。
进行删除复合主键的方式和上面进行删除主键的方式一样,追加主键也是同上
自增长
auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得 到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。
当我们没有进行设置自增长的默认值时,默认是从1开始进行自增长。
自增长的起始值是可以进行设置的
在表已经创建完成后,进行插入值后,如果值插入成功,自增长的起始值进行更新成最新的
alter table users auto_increment= 想要进行设置的自增长起始值;
任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
索引简单的理解(初步)
索引,加快mysql查找速率的(以空间来换时间)
索引: 在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中 一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录, 可以根据目录中的页码快速找到所需的内容。 索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引以 找到特定值,然后顺指针找到包含该值的行。这样可以使对应于表的SQL语句执行得更快,可快速访问数据库表中的 特定信息
唯一键
表达了类似于主键的功能,并且可以为空,null并不参有主键的计算,这不就是阉割版的主键吗?那么我们直接用主键不就可以了,为什么还要用唯一键呢?其实不然,比如人身上有各种属性,表就是相当于结构体,进行描述这种属性,选择了一个属性作为主键,但是其他属性也是需要维持唯一性的???
如何进行理解上述的表达呢?举个例子:
我们进行建立学生管理系统,其中数据库的设计中选取需要进行存储的字段是学号、姓名、手机号选取学号作为主键,但是手机号也是不能重复的,假如没有进行将手机号进行约束,当进行统计学生信息的时候,有可能出现进行复制上一个同学的信息,但是没有进行修改手机号(假如忘记忘记了),当想要进行通过手机号进行查询同学时就出现了问题,这时候唯一键的作用就体现出来了。
mysql> create table student (
-> id char(10) unique comment '学号,不能重复,但可以为空',
-> name varchar(10)
-> );
唯一键的本质是和主键进行配合起来进行,增加表的约束性
功能和逻辑的侧重点
对比维度 | 主键(PRIMARY KEY) | 唯一键(UNIQUE KEY) |
---|---|---|
唯一性约束 | ✅ 强制唯一性 | ✅ 强制唯一性 |
允许 NULL | ❌ 不允许 NULL 值 | ✅ 允许多个 NULL(但值不重复) |
数量限制 | 每张表只能有一个主键 | 可以有多个唯一键 |
默认索引 | 自动创建聚簇索引(InnoDB 引擎下) | 自动创建唯一索引 |
主导意义 | 表的唯一标识,业务核心字段 | 业务上具有唯一性但不是主标识的辅助字段 |
定义位置 | 通常用于 ID、身份证号等主键字段 | 常用于用户名、邮箱、手机号等登录识别字段 |
语义含义 | 强调主身份标识(逻辑主键) | 强调字段值不能重复(唯一约束) |
外键
外键更强调的是两点:表和表之间的关联和表跟表之间的约束
用于在尽力从表的使用使用
foreign key (字段名) references 主表(列)
主表是被引用者,保存核心数据;从表是引用者,保存依赖主表的业务数据,二者通过外键约束保持数据的一致性与完整性
我们之前学习的约束都是内聚的,都是在一张表中进行约束,但是mysql是关系型数据库,一张表和其他的表势必会产生联系。
在实际的数据库设计中,很多初学者会提出一个问题:
“既然两张表之间存在关系,为什么不把它们合并成一张表,为什么还要使用外键进行关联?”
这个问题触及到了关系型数据库建模的核心思想:范式设计与数据解耦。通过示例来说明拆表建模的优势。
为什么不直接合并为一张表?
表的拆分并使用外键,是基于以下几个核心原因:
原因 说明 避免冗余 一张大表中会出现重复数据,比如同一个用户下多笔订单会重复存储用户信息。 保持一致性 如果信息变更(如用户手机号),只需改一处,减少数据不一致风险。 结构清晰 每张表只负责一类数据(如用户表/订单表),逻辑更清晰,代码更易维护。 灵活扩展 拆分后可以独立扩展字段、索引或迁移单表,方便系统升级。 支持多对多/一对多关系 单张表无法表达复杂的数据关系,比如学生与课程之间的选课记录。 实际例子说明
假设我们设计一个简单的用户和订单系统。
这是没有使用外键的时候的
user_order_table +----+--------+----------+-----------------+ | id | name | phone | order_detail | +----+--------+----------+-----------------+ | 1 | Alice | 123456 | iPhone 15 | | 1 | Alice | 123456 | MacBook Air | | 2 | Bob | 789012 | AirPods | +----+--------+----------+-----------------+
使用外键之后
用户表
CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(50), phone VARCHAR(20) );
订单表
CREATE TABLE orders ( order_id INT PRIMARY KEY AUTO_INCREMENT, user_id INT, order_detail VARCHAR(100), FOREIGN KEY (user_id) REFERENCES users(id) );
如果是要不使用外键的话,进行更手机号需要在两张表中都进行更改,使用外键直接就解决了这种数据冗余的问题
如何理解外键约束约束的点
当进行继续插入一个课程号为3的学生,按照插入逻辑是没有问题,但是没有课程号为3的班级,业务逻辑是不合理的;当班级中存在学生,直接把班级进行干掉业务逻辑上也是不合理的
外键约束就是用于进行解决这种问题
先进行创建主键表,然后再进行创建从表
班级是先存在的,学生必须隶属于某个班级,所以说班级是主键表
往表中进行插入数据
当进行插入的数据主表中没有对应的外键时,插入会进行报错
在从表中进行删除数据
由于主表中还存在信息,在进行删除的时候也会进行报错。
外键约束还可以进行起名字
CREATE TABLE 从表 ( 字段名 数据类型, ... CONSTRAINT 外键名 FOREIGN KEY (外键字段) REFERENCES 主表(主键字段) );