# P30 30. 基础-函数-流程函数

> 本页是学习笔记，不等同于视频逐字稿。原声字幕未取得（匿名接口字幕轨为空且需登录，未使用任何账号），也没有逐句讲解记录；讲义只按节与页码对应，切点未逐句确证。

> 以同版讲义的公开镜像核对章节与页码（镜像非官方出品）；非逐字稿，示例为原创补充。

## P30 30. 基础-函数-流程函数

- 原视频：https://www.bilibili.com/video/BV1Kr4y1i7ru/?p=30（p=30），时长 12:01
- 讲义：3.4 流程函数 p59–61（公开镜像；按主题对应，切点 notexact）

- 本集练习数据：practice/p30.sql（先执行，再对照小例）

### 一句话理解

流程函数让一行数据按条件走不同分支：两选一用 IF，空值兜底用 IFNULL，分档用 CASE。

### 跟播：视频里 ↔ 本站

视频演示 IF、IFNULL 与两种 CASE，并用「工作地址分档」做例子。

| 视频里 / 原课字段 | 本站对应 |
|---|---|
| emp.salary / emp.dept_id / emp.workaddress | employee.salary / employee.dept_id（本站没有 workaddress 列） |
| IF(value,t,f)、CASE 列 WHEN 值 | 同左，示例换成薪资与部门两列 |

看完应能：能分清 IF 两选一、简单 CASE 等值分档、搜索 CASE 条件分档，并知道 NULL 要用 IS NULL

看视频时以讲义表为准，跟练时用本站表；结构相同、数字不同。

### 步骤

1. IF(条件, 真值, 假值)：只做两选一。比如「有没有定薪」——条件成立给一个值，否则给另一个。
2. IFNULL(值, 兜底值) 只在值为 NULL 时返回兜底；NULLIF(a,b) 在 a 等于 b 时返回 NULL，用来把某个值「变成空」。
3. CASE 有两种写法：`CASE 列 WHEN 值 THEN …` 只能做等值分档（列名只写一次）；`CASE WHEN 条件 THEN …` 能写范围和多条件。
4. 分支顺序很重要：CASE 自上而下，命中即停；范围宽的条件放前面会把后面的分支挡掉，所以先具体后宽泛。

### SQL 示例

```
SELECT name,
       IFNULL(salary, 0) AS 薪资显示,
       CASE WHEN salary IS NULL THEN '未定薪'
            WHEN salary >= 10000 THEN '高'
            ELSE '普通' END AS 档位
FROM employee
ORDER BY id;
```

说明：【原创演示】四行练习数据逐行判断：小林 8000 → 普通；小周 10000 → 高；小陈 12000 → 高；小李 salary 为 NULL，IFNULL 显示 0，CASE 第一个分支命中得“未定薪”。结果四行按 id 排列。如果把 CASE 写成 `CASE WHEN salary >= 10000 THEN '高' ELSE '普通' END`（漏掉 IS NULL 分支），NULL 参与比较得到未知、不成立，就会落到 ELSE 变成「普通」——没定薪的人被算成普通，语义就错了。

### IF：两选一（有没有定薪）

```sql
SELECT id, name,
       IF(salary IS NULL, '未定薪', '已定薪') AS 状态
FROM employee
ORDER BY id;
```

说明：四行：小林、小周、小陈是「已定薪」，小李是「未定薪」。IF 的三个参数是条件、真值、假值。判断空值必须写 IS NULL；写 salary = NULL 永远不成立，会全部落到假值。

预期结果：4 行：小林/小周/小陈 已定薪；小李 未定薪

### 简单 CASE：按列的值等值分档

```sql
SELECT id, name,
       CASE dept_id
         WHEN 1 THEN '研发'
         WHEN 2 THEN '市场'
         ELSE '未分配'
       END AS 部门
FROM employee
ORDER BY id;
```

说明：四行：小林、小周「研发」，小陈「市场」，小李「未分配」（dept_id 是 NULL，两个 WHEN 都不等于）。简单 CASE 把列名写在 CASE 后面只写一次，后面只写要比较的值；它只能做等值判断，要写「salary >= 10000」这种范围就得换成搜索式 CASE WHEN 条件。

预期结果：4 行：研发、研发、市场、未分配

### 易错点

- 以为 IFNULL 也能处理空字符串：'' 不是 NULL，会原样返回，兜底不生效。
- 在 CASE 里写 salary = NULL 判断空值：与 NULL 比较得到未知，永远不成立，必须用 IS NULL。
- 把简单 CASE 当成万能：`CASE dept_id WHEN 1` 只能比值，写 `WHEN salary > 10000` 会变成「salary 是否等于 10000 的布尔值」，结果不对。

### 30 秒速记

IF 两选一；IFNULL 只认 NULL；NULLIF 相等转空；简单 CASE 等值分档、搜索 CASE 条件分档；先具体后宽泛。

### 自测

1. IFNULL(salary,0) 会不会把薪资为 0 的人也显示成 0？
   - 答：会显示 0，但那本来就是 0；它的问题是无法区分“原本是 0”和“原本是 NULL”，需要区分时用 CASE 单独判断 IS NULL。
2. CASE 的分支顺序为什么会影响结果？
   - 答：CASE 一旦命中就停止判断，范围宽的条件放前面会截走本应属于后面分支的行，所以更具体的条件要写在前面。

### 材料与来源

- [平台视频页] P30 原视频页（BV1Kr4y1i7ru） https://www.bilibili.com/video/BV1Kr4y1i7ru/?p=30
- [官方文档] MySQL 8.0 Reference：流程控制函数 https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html

证据说明：按 t40 帧核对：画面是 Workbench 里 IFNULL 的演示（对 'OK'、''、NULL 三种入参分别调用），并出现「case when then else end」的注释与地址分档需求；讲义 p59「3.4 流程函数」表格四行正是 IF / IFNULL / CASE WHEN 条件 / CASE 表达式 WHEN 值。正文示例为原创，使用自己的练习表，未照抄课堂表与数据；原声字幕未取得，讲师结论未核实。
