MySQL DCL、函数与约束详解( 安全、效率、完整性的三板斧)

 更新时间:2026年09月18日 09:34:55   作者:泡泡鱼(敲代码中)  
这篇文章给大家介绍MySQL学习笔记:DCL、函数与约束 —— 安全、效率、完整性的三板斧,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

学完 DML 的增删改、DQL 的查询之后,昨天把 MySQL 基础篇剩下的三块硬骨头啃完了: DCL(数据控制语言)、函数、约束。这三块内容看起来零散,其实各守一条主线:

  • DCL → 安全:谁能连我的数据库?连上能干什么?
  • 函数 → 效率:把计算交给数据库,而不是拿回程序里算;
  • 约束 → 正确性:从源头拦住脏数据,保证数据完整。

这篇笔记把三块内容串起来讲,语法 + 案例 + 我的理解,希望能帮到同样在学 MySQL 的朋友。

一、DCL:数据库的 “门禁系统”

DCL 全称 Data Control Language(数据控制语言),用来管理数据库用户、控制访问权限。这类 SQL 开发人员用得少,主要是 DBA(数据库管理员)在操作,但理解它对你理解 “数据库安全” 很有帮助。

1.1 管理用户:用户 = 用户名 @ 主机名

在 MySQL 中,一个用户不是只有 “用户名”,而是由用户名 + 主机名共同唯一标识:

-- 查询所有用户(用户信息存放在 mysql 库的 user 表)
SELECT * FROM mysql.user;
-- 创建用户:'itcast' 只能在本机(localhost)访问
CREATE USER 'itcast'@'localhost' IDENTIFIED BY '123456';
-- 创建用户:'heima' 可以在任意主机(%)访问
CREATE USER 'heima'@'%' IDENTIFIED BY '123456';
-- 修改密码(mysql_native_password 是认证插件)
ALTER USER 'heima'@'%' IDENTIFIED WITH mysql_native_password BY '1234';
-- 删除用户
DROP USER 'itcast'@'localhost';

关键点

  • Host 表示该用户允许从哪台主机访问:localhost 只允许本机,% 是通配符,允许任意主机;
  • 所以 'itcast'@'localhost''itcast'@'%' 是两个不同的用户
  • 这类操作主要面向 DBA,开发人员平时接触不多。

1.2 权限控制:能干什么,细到 “库。表”

-- 查询某用户的权限
SHOW GRANTS FOR 'heima'@'%';
-- 授予权限:授予 heima 操作 itcast 库所有表的所有权限
GRANT ALL ON itcast.* TO 'heima'@'%';
-- 撤销权限
REVOKE ALL ON itcast.* FROM 'heima'@'%';

常见权限有:ALL / ALL PRIVILEGES(所有)、SELECTINSERTUPDATEDELETEALTERDROPCREATE 等。

关键点

  • 多个权限用逗号分隔:GRANT SELECT, INSERT, UPDATE ON itcast.* TO ...;
  • 数据库名.表名 支持 * 通配:itcast.* 表示 itcast 库的所有表,*.* 表示所有库的所有表;
  • 权限粒度可以精确到 “某个库的某张表”,这就是 “最小权限” 的基础。

最小权限原则是数据库安全的第一课:给用户只授 “够用” 的权限。业务账号通常只需要 SELECT/INSERT/UPDATE/DELETE,结构变更(ALTER/DROP)留给 DBA 账号。别图省事直接 GRANT ALL

Host 就是安全边界:'xxx'@'%' 等于把数据库暴露给任意 IP。生产环境如果业务账号用了 %,风险相当大 —— 最好精确到应用服务器所在的网段或具体 IP。

生产环境不要用 root 跑业务:root 权限无法精细限制,出了问题也没有追溯手段。这也是 “最小权限账号” 存在的意义。

补充两点课件没细说的:

  • MySQL 8 默认认证插件是 caching_sha2_password,老版本客户端连不上时,才需要改成 mysql_native_password
  • 老版本手册里经常出现 FLUSH PRIVILEGES,现在 GRANT/REVOKE 会立即生效,一般不需要手动刷新。

二、函数:把计算交给数据库

函数是 MySQL 内置好的一段可调用代码,业务里直接调用即可。课件用两个场景引入:算入职天数(用 DATEDIFF)、判分数等级(用 CASE WHEN)。MySQL 函数分四类:字符串、数值、日期、流程。

2.1 字符串函数

函数功能
CONCAT(S1,S2,...)字符串拼接
LOWER(str) / UPPER(str)全部转小写 / 转大写
LPAD(str,n,pad) / RPAD(str,n,pad)左 / 右填充到 n 个字符
TRIM(str)去掉首尾空格
SUBSTRING(str,start,len)从 start 起截取 len 个字符

经典案例 —— 工号补零:业务变更要求工号统一为 5 位,不足前面补 0:

UPDATE emp SET workno = LPAD(workno, 5, '0');
-- 1号员工工号 1 → 00001

这个场景在真实业务里非常常见:订单号、学号、流水号要统一长度,LPAD/RPAD 就是干这个的。

2.2 数值函数

函数功能
CEIL(x)向上取整
FLOOR(x)向下取整
MOD(x,y)x/y 的模(余数)
RAND()返回 0~1 随机数
ROUND(x,y)四舍五入,保留 y 位小数

经典案例 ——6 位随机验证码

SELECT LPAD(ROUND(RAND() * 1000000, 0), 6, '0');

思路拆解:RAND() 得到 0~1 随机数 → 乘 1000000 放大 → ROUND(...,0) 取整去掉小数 → LPAD(...,6,'0') 不足 6 位补零。三个函数嵌套在一起,从里往外读,逻辑很清晰。

2.3 日期函数

函数功能
CURDATE() / CURTIME() / NOW()当前日期 / 当前时间 / 当前日期时间
YEAR(date) / MONTH(date) / DAY(date)提取年 / 月 / 日
DATE_ADD(date, INTERVAL expr type)日期加指定时间间隔
DATEDIFF(date1, date2)两个日期相差天数

经典案例 —— 入职天数:查询所有员工的入职天数,按入职天数倒序:

SELECT name, DATEDIFF(CURDATE(), entrydate) AS 'entrydays'
FROM emp
ORDER BY entrydays DESC;

2.4 流程函数

函数功能
IF(value, t, f)value 为真返回 t,否则返回 f
IFNULL(value1, value2)value1 非空返回它,否则返回 value2
CASE WHEN 条件 THEN 结果 ... ELSE 默认 END条件判断(可多分支)
CASE 表达式 WHEN 值 THEN 结果 ... END等值判断

经典案例 —— 工作地址分级:北京 / 上海 → 一线城市,其他 → 二线城市:

SELECT name,
       (CASE workaddress WHEN '北京' THEN '一线城市'
                         WHEN '上海' THEN '一线城市'
                         ELSE '二线城市' END) AS '工作地址'
FROM emp;

经典案例 —— 成绩分档:≥85 优秀、≥60 及格、否则不及格(注意这里用的是 CASE WHEN 条件式写法,因为要做范围判断):

SELECT id, name,
       (CASE WHEN math >= 85 THEN '优秀'
             WHEN math >= 60 THEN '及格'
             ELSE '不及格' END) AS '数学',
       (CASE WHEN english >= 85 THEN '优秀'
             WHEN english >= 60 THEN '及格'
             ELSE '不及格' END) AS '英语'
FROM score;

单行函数 vs 聚合函数:今天学的都是单行函数(对一行数据计算,返回一行结果);之前学的 COUNT/AVG/MAX聚合函数(多行压成一行)。搞清楚这个分类,读 SQL 心里更有数。

函数可以嵌套:验证码案例就是三层嵌套。嵌套函数的读法是 “从里往外”—— 最里层先算,结果作为外层参数。

几个易错点

  • SUBSTRING 的起始位置从 1 开始SUBSTRING('Hello MySQL', 1, 5) 结果是 Hello
  • TRIM 只去首尾空格,不去中间空格;
  • IFNULL 只认 NULL:IFNULL('', 'Default') 返回 ''(空字符串不是 NULL,不会走默认值);
  • 两种 CASE 写法别混用:CASE 字段 WHEN 值 只能做等值判断,范围判断必须用 CASE WHEN 条件

补充常用函数(课件没列但很常用):CHAR_LENGTH(字符数)、REPLACE(替换)、DATE_FORMAT(日期格式化)、TIMESTAMPDIFF(更灵活的时间差)、LAST_DAY(当月最后一天)。

一个进阶提醒:在 WHERE 里对字段套函数(如 WHERE YEAR(entrydate) = 2020)会导致该字段的索引失效、全表扫描。函数不是随便放哪都行,“函数用在哪” 是 SQL 优化的经典考点,进阶篇会展开。

三、约束:数据完整性的守门员

概念:约束是作用于表中字段上的规则,用于限制存储的数据。目的:保证数据库中数据的正确性、有效性和完整性

3.1 六种约束总览

约束描述关键字
非空约束限制字段不能为 NULLNOT NULL
唯一约束保证字段值唯一、不重复UNIQUE
主键约束一行数据的唯一标识,非空且唯一PRIMARY KEY
默认约束未指定值时采用默认值DEFAULT
检查约束(8.0.16+)保证字段值满足某个条件CHECK
外键约束让两张表建立连接,保证一致性FOREIGN KEY

约束可以在创建表修改表时添加。

3.2 一个建表演示

CREATE TABLE tb_user(
    id int AUTO_INCREMENT PRIMARY KEY COMMENT 'ID唯一标识',
    name varchar(10) NOT NULL UNIQUE COMMENT '姓名',
    age int CHECK (age > 0 && age <= 120) COMMENT '年龄',
    status char(1) DEFAULT '1' COMMENT '状态',
    gender char(1) COMMENT '性别'
);

验证约束是否生效:

  • name = NULL → 违反 NOT NULL,报错;
  • 插重复 name → 违反 UNIQUE,报错;
  • age = -1age = 121 → 违反 CHECK,报错;
  • 不填 status → 自动变成默认值 '1'DEFAULT 生效)。

3.3 外键约束:让两张表 “拉上关系”

外键用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。典型场景:员工表 emp.dept_id 关联部门表 dept.id

课件里做了一个很好的实验:不建外键时,直接删除 dept 表 id=1 的部门会成功,但 emp 表里还有一堆员工挂着 dept_id=1—— 数据 “悬空” 了,这就是不一致。外键就是来解决这个问题的。

-- 建表时添加外键
[CONSTRAINT 外键名] FOREIGN KEY (外键字段) REFERENCES 主表(主键列);
-- 给已有表添加外键(emp.dept_id → dept.id)
ALTER TABLE emp ADD CONSTRAINT fk_emp_dept_id
FOREIGN KEY (dept_id) REFERENCES dept(id);
-- 删除外键
ALTER TABLE emp DROP FOREIGN KEY fk_emp_dept_id;

加了外键之后,再删除 dept 里被引用的记录会直接报错—— 外键生效了。

删除 / 更新行为:父表记录被删 / 改时,子表怎么办?有四种选择(配图见下):

行为效果
NO ACTION / RESTRICT子表有引用就拒绝删除 / 更新(默认,两者一致)
CASCADE子表级联删除 / 更新
SET NULL子表外键列置为 NULL(要求外键允许 NULL)
SET DEFAULT置为默认值(InnoDB 不支持
-- 级联示例:父表更新/删除时,子表跟着变
ALTER TABLE emp ADD CONSTRAINT fk_emp_dept_id
FOREIGN KEY (dept_id) REFERENCES dept(id)
ON UPDATE CASCADE ON DELETE CASCADE;

约束的本质是把规则交给数据库。没有约束时,数据质量只能靠应用代码 “自觉”;一旦换入口(DBA 直接改库、脚本批量导入),脏数据就进来了。约束是数据库层面的守门员,从源头拦截。

主键 vs 唯一约束

  • 主键 = 非空 + 唯一,一张表只能有一个主键;
  • 唯一约束可以有多个,而且唯一约束允许多个 NULL(NULL 之间不算重复);
  • 两者都会自动创建索引(这也是 “约束顺便建索引” 的知识点)。

CHECK 约束的版本坑CHECK 语法在 MySQL 5.7 就能写,但 8.0.16 之前会被静默忽略—— 不报错、不生效。所以别以为写了 CHECK 就万事大吉,先确认版本。

外键 vs 逻辑外键(面试高频)

  • 用外键:一致性由数据库强制保证,安全;
  • 不用外键:每次增删改都要检查关联,有性能开销;父表删除受限,业务不灵活;表间强耦合。
  • 现实里很多互联网公司用 “逻辑外键”—— 表里存 dept_id,但不在数据库建外键,由应用层保证一致性。我的观点:数据一致性要求高、写并发低的系统用外键;高并发互联网场景常用逻辑外键 + 应用层校验。面试时能说出这个取舍,比单纯背定义强得多。

CASCADE 是双刃剑:级联删除确实方便,但 DELETE FROM dept WHERE id=1 可能连带删掉几百条员工记录,删错不可逆。生产环境对级联要非常谨慎。课件也提醒:业务系统中一般不会修改主键值

四、写在最后

至此,MySQL 基础篇的 SQL 五类语言(DDL、DML、DQL、DCL、TCL)已经学完四类,下一站是多表查询和事务。

练习建议:把 tb_user 建出来亲手试一遍约束;用 emp 表分别实现 “工号补零”" 入职天数 "“工作地址分级” 三个案例;再试试给两张表加外键,观察 CASCADESET NULL 的区别 —— 动手跑一遍,比看十遍笔记记得牢。

到此这篇关于MySQL DCL、函数与约束详解( 安全、效率、完整性的三板斧)的文章就介绍到这了,更多相关MySQL DCL、函数与约束内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SQL高级特性实战之窗口函数、JSONB与多数据库兼容完全指南

    SQL高级特性实战之窗口函数、JSONB与多数据库兼容完全指南

    SQL中的JSON函数让数据库能直接解析、查询和构造JSON数据,无需在应用层反复序列化/反序列化,这篇文章主要介绍了SQL高级特性实战之窗口函数、JSONB与多数据库兼容的相关资料,需要的朋友可以参考下
    2026-06-06
  • MySQL 字段默认值该如何设置

    MySQL 字段默认值该如何设置

    这篇文章主要介绍了MySQL 字段默认值该如何设置,帮助大家更好的理解和学习使用MySQL,感兴趣的朋友可以了解下
    2021-02-02
  • MySQL索引详细解析

    MySQL索引详细解析

    索引是有双面性的,合理的建立索引可以提高数据库的效率。但是如果没有合理的构建索引和使用索引,可能会导致索引失效或者影响数据库性能,这篇文章主要介绍了MySql索引原理与操作
    2022-10-10
  • MySQL设置数据格为空白或NULL问题及解决

    MySQL设置数据格为空白或NULL问题及解决

    文章主要讨论了在处理数据库需求时将某些字段设置为空白的问题,初尝试直接传递空字符串,PHPMyAdmin提示需要三个值,实际是因第三列数据不足导致.后文提出可通过设置字段默认值为NULL或直接写入空字符串来解决;并指出NULL与空字符串的区别
    2026-04-04
  • MySQL执行SQL文件报错:Unknown collation ‘utf8mb4_0900_ai_ci‘的解决方案

    MySQL执行SQL文件报错:Unknown collation ‘utf8mb4_0900_ai_

    这篇文章主要给大家分享了MySQL执行SQL文件出现【Unknown collation ‘utf8mb4_0900_ai_ci‘】的解决方案,如果又遇到相同问题的同学,可以参考阅读本文
    2023-09-09
  • MySql使用skip-name-resolve解决外网链接客户端过慢问题

    MySql使用skip-name-resolve解决外网链接客户端过慢问题

    在腾讯云上面搭建的mysql使用开发的电脑上navicat进行访问时总是特别的慢,原来是Mysql会对请求的地址进行域名解析,开发的电脑并没有域名,所以会导致特别的慢,下面通过本文给大家分享MySql使用skip-name-resolve解决外网链接客户端过慢问题
    2017-07-07
  • windows系统中MySQL和SQLyog的安装和配置教程

    windows系统中MySQL和SQLyog的安装和配置教程

    这篇文章主要介绍了windows系统中MySQL和SQLyog的安装和配置教程的相关资料,包括下载MySQL、解压、设置环境变量、初始化数据库、修改密码等步骤,同时还介绍了如何下载和安装SQLyog图形化工具,以便更方便地管理和操作MySQL数据库,需要的朋友可以参考下
    2025-11-11
  • 5分钟了解MySQL5.7中union all用法的黑科技

    5分钟了解MySQL5.7中union all用法的黑科技

    本文带领大家通过5分钟了解MySQL5.7中union all用法的黑科技,需要的朋友可以参考下
    2017-04-04
  • MySQL中回表查询避免和优化指南

    MySQL中回表查询避免和优化指南

    在开发和运维中,要想设计高效的数据库系统,要想优化提升SQL查询性能,都离不开一个理论知识:回表查询,本篇文章我们以具体的案例来介绍一下MySQL中,回表查询相关的知识、案例以及优化方案,需要的朋友可以参考下
    2025-09-09
  • Docker安装MySQL镜像的详细步骤(适合新手小白)

    Docker安装MySQL镜像的详细步骤(适合新手小白)

    本文详细介绍了如何在Ubuntu环境下使用Docker安装MySQL5.7版本,包括从官网拉取镜像、配置MySQL容器、设置权限及内网部署,为读者展示了容器化MySQL的实践过程,需要的朋友可以参考下
    2025-05-05

最新评论