MySQL 函数分类速查表

适用于 MySQL 8.x 学习与日常开发。本文优先详细介绍高频函数,低频函数只给出用途和基本语法。

1. 标记说明

本文使用以下标记:

标记 含义
[SQL] 属于 SQL 标准,或者具有明确的标准 SQL 形式;主流关系数据库通常提供相同或相近能力
[MySQL] MySQL 方言提供的函数、别名或特有语法;迁移到其他数据库时通常需要改写

需要注意:

2. 快速索引

分类 高频内容
聚合 COUNTSUMAVGMINMAXGROUP_CONCAT
字符串 CONCATCHAR_LENGTHLENGTHSUBSTRINGTRIMREPLACE
日期时间 CURRENT_TIMESTAMPDATE_ADDDATE_SUBDATEDIFFTIMESTAMPDIFFDATE_FORMAT
数值 ROUNDCEILFLOORABSMOD
NULL 与条件 COALESCENULLIFCASEIFIFNULL
类型转换 CASTCONVERT
JSON JSON_EXTRACTJSON_SETJSON_OBJECTJSON_ARRAYAGG
窗口函数 ROW_NUMBERRANKLAGLEAD、聚合函数 OVER()
系统信息 DATABASECURRENT_USERVERSIONLAST_INSERT_ID

3. 聚合函数

聚合函数把多行数据计算成一个结果。它们经常与 GROUP BYHAVING 配合使用。

3.1 COUNT():统计数量

标记:[SQL]

语法:

COUNT(*)
COUNT(expression)
COUNT(DISTINCT expression)

区别:

写法 含义
COUNT(*) 统计行数,不关心某列是否为 NULL
COUNT(column) 只统计该列不是 NULL 的行
COUNT(DISTINCT column) 统计去重后的非 NULL 值数量

示例:

SELECT COUNT(*) AS actor_count
FROM actor;
SELECT
  COUNT(*) AS total_rows,
  COUNT(return_date) AS returned_rows
FROM rental;

return_date 允许为 NULL 时,两者可能不同。

按客户统计租赁次数:

SELECT
  customer_id,
  COUNT(*) AS rental_count
FROM rental
GROUP BY customer_id
ORDER BY rental_count DESC;

经验:

3.2 SUM():求和

标记:[SQL]

语法:

SUM(expression)
SUM(DISTINCT expression)

示例:

SELECT SUM(amount) AS total_amount
FROM payment;

按客户统计付款总额:

SELECT
  customer_id,
  SUM(amount) AS total_amount
FROM payment
GROUP BY customer_id;

没有匹配行时,SUM() 通常返回 NULL,不是 0

SELECT COALESCE(SUM(amount), 0) AS total_amount
FROM payment
WHERE customer_id = -1;

金额列应使用 DECIMAL,不要依赖浮点数完成精确财务计算。

3.3 AVG():平均值

标记:[SQL]

语法:

AVG(expression)
AVG(DISTINCT expression)

示例:

SELECT AVG(length) AS average_length
FROM film;

AVG(column) 会忽略 NULL。如果业务要求把缺失值视为零,需要明确写出:

SELECT AVG(COALESCE(score, 0))
FROM exam_result;

但这会改变统计含义,不能为了消除 NULL 随意使用。

3.4 MIN()MAX():最小值与最大值

标记:[SQL]

语法:

MIN(expression)
MAX(expression)

示例:

SELECT
  MIN(amount) AS minimum_amount,
  MAX(amount) AS maximum_amount
FROM payment;

不仅能处理数字,也能处理日期和字符串:

SELECT
  MIN(payment_date) AS first_payment_at,
  MAX(payment_date) AS last_payment_at
FROM payment;

3.5 GROUP_CONCAT():把多行拼接成字符串

标记:[MySQL]

语法:

GROUP_CONCAT(
  [DISTINCT] expression
  [ORDER BY expression]
  [SEPARATOR 'separator']
)

查询电影对应的演员姓名:

SELECT
  f.film_id,
  f.title,
  GROUP_CONCAT(
    CONCAT(a.first_name, ' ', a.last_name)
    ORDER BY a.last_name, a.first_name
    SEPARATOR ', '
  ) AS actors
FROM film AS f
JOIN film_actor AS fa ON fa.film_id = f.film_id
JOIN actor AS a ON a.actor_id = fa.actor_id
GROUP BY f.film_id, f.title;

注意:


4. 字符串函数

4.1 CONCAT():拼接字符串

标记:[MySQL]

语法:

CONCAT(value1, value2, ...)

示例:

SELECT CONCAT(first_name, ' ', last_name) AS full_name
FROM actor;

MySQL 中只要任意参数是 NULLCONCAT() 就返回 NULL

SELECT CONCAT('Hello', NULL); -- NULL

需要忽略 NULL 时可以使用 CONCAT_WS()

4.2 CONCAT_WS():使用分隔符拼接

标记:[MySQL]

语法:

CONCAT_WS(separator, value1, value2, ...)

示例:

SELECT CONCAT_WS(', ', address, district, postal_code) AS address_text
FROM address;

CONCAT_WS() 会跳过后续参数中的 NULL,但不会自动跳过空字符串。

4.3 CHAR_LENGTH()LENGTH()

CHAR_LENGTH()[SQL]
LENGTH()[MySQL],在 MySQL 中统计字节数。

语法:

CHAR_LENGTH(string)
LENGTH(string)

示例:

SELECT
  CHAR_LENGTH('中国') AS character_count,
  LENGTH('中国') AS byte_count;

utf8mb4 下通常会得到:

character_count = 2
byte_count = 6

判断用户可见字符数时通常使用 CHAR_LENGTH(),检查存储字节数时才使用 LENGTH()

4.4 LOWER()UPPER():大小写转换

标记:[SQL]

语法:

LOWER(string)
UPPER(string)

示例:

SELECT
  LOWER(email) AS normalized_email,
  UPPER(first_name) AS upper_name
FROM customer;

是否区分大小写主要受字符集和排序规则影响。不要仅靠查询时 LOWER(email) 保证邮箱唯一,最终仍应设计合适的 MySQL 唯一索引和 collation。

4.5 TRIM():去除两端字符

标记:[SQL]

常用语法:

TRIM(string)
TRIM([BOTH | LEADING | TRAILING] remove_string FROM string)

示例:

SELECT TRIM('  hello  ');                -- 'hello'
SELECT TRIM(LEADING '0' FROM '000123');  -- '123'
SELECT TRIM(TRAILING '.' FROM 'abc...'); -- 'abc'

关联函数:

LTRIM(string)
RTRIM(string)

LTRIM()RTRIM() 在 MySQL 中常用,但可移植性不如标准 TRIM() 写法。

4.6 SUBSTRING():截取字符串

标记:[SQL],MySQL 同时支持多种简写。

语法:

SUBSTRING(string, start)
SUBSTRING(string, start, length)
SUBSTRING(string FROM start FOR length)

示例:

SELECT SUBSTRING('abcdef', 2, 3); -- 'bcd'

MySQL 字符位置从 1 开始。负数表示从末尾开始:

SELECT SUBSTRING('abcdef', -3); -- 'def'

4.7 LEFT()RIGHT()

标记:[MySQL]

语法:

LEFT(string, length)
RIGHT(string, length)

示例:

SELECT LEFT('abcdef', 3);  -- 'abc'
SELECT RIGHT('abcdef', 3); -- 'def'

4.8 REPLACE():替换字符串

标记:[MySQL]

语法:

REPLACE(string, from_string, to_string)

示例:

SELECT REPLACE('2026/08/09', '/', '-');

这是字符串替换函数,不等同于 MySQL 的 REPLACE INTO 写入语句。

4.9 LOCATE()INSTR()POSITION():查找位置

POSITION()[SQL]
LOCATE()INSTR()[MySQL]

语法:

POSITION(substring IN string)
LOCATE(substring, string [, start])
INSTR(string, substring)

示例:

SELECT POSITION('@' IN 'user@example.com');
SELECT LOCATE('@', 'user@example.com');

找不到时返回 0

4.10 LPAD()RPAD():补齐长度

标记:[MySQL]

语法:

LPAD(string, target_length, pad_string)
RPAD(string, target_length, pad_string)

示例:

SELECT LPAD('123', 6, '0'); -- '000123'

它适合生成展示文本,不代表数据库主键本身应该保存成补零字符串。

4.11 其他低频字符串函数

函数 标记 用途
REVERSE(string) [MySQL] 反转字符串
REPEAT(string, count) [MySQL] 重复字符串
SPACE(count) [MySQL] 生成指定数量空格
ASCII(string) [MySQL] 返回首字符 ASCII 值
CHAR(number, ...) [MySQL] 从字符编码生成字符串
HEX(value)UNHEX(value) [MySQL] 十六进制编码与解码
FIND_IN_SET(value, csv) [MySQL] 在逗号字符串中查找位置,不建议替代关联表

5. 日期和时间函数

5.1 获取当前日期和时间

标准形式:

CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP

标记:[SQL]

MySQL 常用别名:

CURDATE()
CURTIME()
NOW()

标记:[MySQL]

示例:

SELECT
  CURRENT_DATE,
  CURRENT_TIME,
  CURRENT_TIMESTAMP;

NOW() 在同一条语句执行期间通常保持一致。需要明确数据库会话时区,否则 Node.js、MySQL 与用户时区可能产生理解差异。

5.2 DATE()TIME():取日期或时间部分

标记:[MySQL]

语法:

DATE(datetime_expression)
TIME(datetime_expression)

示例:

SELECT DATE(payment_date), TIME(payment_date)
FROM payment;

不要习惯性这样查询某一天:

WHERE DATE(payment_date) = '2026-08-09'

对列使用函数可能使普通索引难以直接完成范围定位。更推荐:

WHERE payment_date >= '2026-08-09 00:00:00'
  AND payment_date <  '2026-08-10 00:00:00'

这就是左闭右开时间范围。

5.3 EXTRACT():提取日期部分

标记:[SQL]

语法:

EXTRACT(unit FROM datetime_expression)

示例:

SELECT
  EXTRACT(YEAR FROM payment_date) AS payment_year,
  EXTRACT(MONTH FROM payment_date) AS payment_month
FROM payment;

MySQL 还提供快捷函数:

YEAR(date)
MONTH(date)
DAY(date)
HOUR(datetime)
MINUTE(datetime)
SECOND(datetime)

这些快捷函数标记为 [MySQL]

5.4 DATE_ADD()DATE_SUB():日期加减

标记:[MySQL]

语法:

DATE_ADD(date, INTERVAL value unit)
DATE_SUB(date, INTERVAL value unit)

示例:

SELECT DATE_ADD('2026-08-09', INTERVAL 1 DAY);
SELECT DATE_SUB('2026-08-09', INTERVAL 7 DAY);
SELECT DATE_ADD('2026-08-09 10:30:00', INTERVAL 2 HOUR);

MySQL 也支持运算形式:

date_expression + INTERVAL 1 DAY
date_expression - INTERVAL 1 DAY

高频单位:

SECOND
MINUTE
HOUR
DAY
WEEK
MONTH
QUARTER
YEAR

月份加减要注意月底规则,例如 1 月 31 日加一个月的结果不能简单理解成固定增加 30 天。

5.5 DATEDIFF():相差多少天

标记:[MySQL]

语法:

DATEDIFF(end_date, start_date)

示例:

SELECT DATEDIFF('2026-08-10', '2026-08-01'); -- 9

DATEDIFF() 只比较日期部分,忽略具体时分秒。

5.6 TIMESTAMPDIFF():按指定单位计算差值

标记:[MySQL]

语法:

TIMESTAMPDIFF(unit, start_datetime, end_datetime)

示例:

SELECT TIMESTAMPDIFF(
  HOUR,
  '2026-08-09 08:00:00',
  '2026-08-10 10:30:00'
); -- 26

注意参数顺序与 DATEDIFF(end, start) 不完全一样:

DATEDIFF(end, start)
TIMESTAMPDIFF(unit, start, end)

这是很常见的记忆陷阱。

5.7 DATE_FORMAT():日期格式化为字符串

标记:[MySQL]

语法:

DATE_FORMAT(datetime_expression, format_string)

示例:

SELECT DATE_FORMAT(payment_date, '%Y-%m-%d %H:%i:%s')
FROM payment;

常用格式:

格式 含义
%Y 四位年份
%m 两位月份
%d 两位日期
%H 24 小时制小时
%i 分钟,注意不是 %m
%s

按月统计:

SELECT
  DATE_FORMAT(payment_date, '%Y-%m') AS payment_month,
  SUM(amount) AS total_amount
FROM payment
GROUP BY DATE_FORMAT(payment_date, '%Y-%m');

用于显示时,很多团队更倾向于让数据库返回原始时间,由应用层根据用户语言和时区格式化。用于报表分组时则很常见。

5.8 STR_TO_DATE():字符串解析成日期

标记:[MySQL]

语法:

STR_TO_DATE(string, format_string)

示例:

SELECT STR_TO_DATE('09/08/2026', '%d/%m/%Y');

不要把它当成接口输入校验的替代品。应用层仍应先校验输入格式,数据库列则应使用真正的 DATEDATETIMETIMESTAMP 类型。

5.9 LAST_DAY():取得月份最后一天

标记:[MySQL]

语法:

LAST_DAY(date)

示例:

SELECT LAST_DAY('2026-02-10'); -- '2026-02-28'

5.10 Unix 时间戳

标记:[MySQL]

UNIX_TIMESTAMP([datetime])
FROM_UNIXTIME(unix_timestamp [, format])

示例:

SELECT UNIX_TIMESTAMP(CURRENT_TIMESTAMP);
SELECT FROM_UNIXTIME(1786248000);

使用时要明确秒和毫秒的区别:JavaScript Date.now() 返回毫秒,而 Unix 时间戳经常以秒表示。

5.11 其他日期函数

函数 标记 用途
DAYOFWEEK(date) [MySQL] 返回星期序号,周日为 1
WEEKDAY(date) [MySQL] 返回星期序号,周一为 0
DAYOFYEAR(date) [MySQL] 一年中的第几天
WEEK(date [, mode]) [MySQL] 周数,受 mode 影响
QUARTER(date) [MySQL] 季度 1–4
MAKEDATE(year, day) [MySQL] 根据年份和一年中的天数构造日期
MAKETIME(hour, minute, second) [MySQL] 构造时间
CONVERT_TZ(datetime, from_tz, to_tz) [MySQL] 转换时区,需要时区表支持

6. 数值函数

6.1 ROUND():四舍五入

标记:[SQL]

语法:

ROUND(number [, decimal_places])

示例:

SELECT ROUND(12.3456, 2); -- 12.35
SELECT ROUND(1234.56, -2); -- 1200

展示金额时可以使用 ROUND(),但数据库字段本身仍应使用正确的 DECIMAL(precision, scale)

6.2 CEIL()CEILING():向上取整

标记:[SQL]

CEIL(number)
CEILING(number)

示例:

SELECT CEIL(3.01); -- 4

6.3 FLOOR():向下取整

标记:[SQL]

FLOOR(number)

示例:

SELECT FLOOR(3.99); -- 3

6.4 ABS():绝对值

标记:[SQL]

ABS(number)

6.5 MOD():取余数

标记:[SQL]

MOD(dividend, divisor)
dividend % divisor

示例:

SELECT MOD(10, 3); -- 1

% 是 MySQL 支持的运算符形式,可移植 SQL 更适合使用 MOD()

6.6 随机数

RAND()[MySQL]

RAND([seed])

示例:

SELECT RAND();

随机取记录:

SELECT film_id, title
FROM film
ORDER BY RAND()
LIMIT 1;

ORDER BY RAND() 会为大量候选行生成随机值并排序,大表上成本很高,只适合小数据集或练习。

6.7 其他数值函数

函数 标记 用途
POWER(x, y) [SQL] x 的 y 次方
SQRT(x) [SQL] 平方根
EXP(x) [SQL] e 的 x 次方
LN(x) [SQL] 自然对数
LOG10(x) [SQL] 以 10 为底的对数
SIGN(x) [SQL] 返回 -1、0 或 1
PI() [MySQL] 圆周率
RADIANS(x) [MySQL] 角度转弧度
DEGREES(x) [MySQL] 弧度转角度
TRUNCATE(x, d) [MySQL] 截断到 d 位小数,不做四舍五入

7. NULL 与条件处理

7.1 COALESCE():取得第一个非 NULL

标记:[SQL]

语法:

COALESCE(value1, value2, ...)

示例:

SELECT COALESCE(address2, '无补充地址')
FROM address;
SELECT COALESCE(SUM(amount), 0)
FROM payment
WHERE customer_id = -1;

它不会把空字符串、0false 当成 NULL

7.2 NULLIF():相等时返回 NULL

标记:[SQL]

语法:

NULLIF(value1, value2)

如果两个值相等,返回 NULL;否则返回第一个值。

避免除零:

SELECT total_amount / NULLIF(order_count, 0)
FROM statistics;

7.3 CASE:标准条件表达式

标记:[SQL]

搜索式语法:

CASE
  WHEN condition1 THEN result1
  WHEN condition2 THEN result2
  ELSE default_result
END

示例:

SELECT
  rental_id,
  CASE
    WHEN return_date IS NULL THEN '租赁中'
    ELSE '已归还'
  END AS rental_status
FROM rental;

简单式语法:

CASE expression
  WHEN value1 THEN result1
  WHEN value2 THEN result2
  ELSE default_result
END

条件聚合:

SELECT
  COUNT(*) AS total_count,
  SUM(CASE WHEN return_date IS NULL THEN 1 ELSE 0 END) AS open_count
FROM rental;

7.4 IF():MySQL 条件函数

标记:[MySQL]

语法:

IF(condition, true_value, false_value)

示例:

SELECT IF(return_date IS NULL, '租赁中', '已归还')
FROM rental;

简单条件可以使用 IF();复杂逻辑和需要可移植性时优先使用 CASE

7.5 IFNULL():MySQL 的二参数空值替代

标记:[MySQL]

IFNULL(value, fallback_value)

示例:

SELECT IFNULL(address2, '无补充地址')
FROM address;

可移植形式是:

COALESCE(address2, '无补充地址')

7.6 GREATEST()LEAST()

标记:[MySQL],其他数据库也可能支持,但兼容性和 NULL 行为需要确认。

GREATEST(value1, value2, ...)
LEAST(value1, value2, ...)

示例:

SELECT GREATEST(10, 20, 5); -- 20
SELECT LEAST(10, 20, 5);    -- 5

MySQL 中任意参数为 NULL 时,结果通常为 NULL


8. 类型转换函数

8.1 CAST():标准类型转换

标记:[SQL]

语法:

CAST(expression AS type)

示例:

SELECT CAST('123' AS UNSIGNED);
SELECT CAST('2026-08-09' AS DATE);
SELECT CAST(amount AS CHAR)
FROM payment;

MySQL 常用目标类型包括:

CHAR
DATE
DATETIME
DECIMAL
SIGNED
UNSIGNED
BINARY
JSON

具体可用类型和转换规则具有 MySQL 方言细节。

8.2 CONVERT()

标记:[MySQL]

类型转换:

CONVERT(expression, type)

字符集转换:

CONVERT(expression USING character_set)

示例:

SELECT CONVERT('123', UNSIGNED);
SELECT CONVERT(column_name USING utf8mb4)
FROM some_table;

8.3 FORMAT():格式化数字显示

标记:[MySQL]

FORMAT(number, decimal_places [, locale])

示例:

SELECT FORMAT(1234567.89, 2); -- '1,234,567.89'

返回的是字符串,适合报表显示,不适合继续参与数值计算。API 的本地化显示通常更适合放在前端或应用层。


9. JSON 函数

MySQL 的 JSON 函数和路径语法具有明显方言特征,本节统一标记为 [MySQL]

9.1 JSON_OBJECT()JSON_ARRAY():构造 JSON

JSON_OBJECT(key, value [, key, value] ...)
JSON_ARRAY(value1, value2, ...)

示例:

SELECT JSON_OBJECT(
  'id', actor_id,
  'name', CONCAT(first_name, ' ', last_name)
) AS actor_json
FROM actor;
SELECT JSON_ARRAY('mysql', 'nodejs', 'typescript');

9.2 JSON_EXTRACT()->

JSON_EXTRACT(json_document, path [, path] ...)
json_column -> path

示例:

SELECT JSON_EXTRACT(profile, '$.address.city')
FROM customer_profile;

简写:

SELECT profile -> '$.address.city'
FROM customer_profile;

返回值仍是 JSON 值,字符串可能带引号。

9.3 JSON_UNQUOTE()->>

JSON_UNQUOTE(json_value)
json_column ->> path

示例:

SELECT profile ->> '$.address.city' AS city
FROM customer_profile;

->> 可以理解为提取并取消 JSON 字符串引号。

9.4 JSON_SET()JSON_INSERT()JSON_REPLACE()

JSON_SET(document, path, value [, path, value] ...)
JSON_INSERT(document, path, value [, path, value] ...)
JSON_REPLACE(document, path, value [, path, value] ...)

区别:

函数 路径不存在 路径已存在
JSON_SET 新增 替换
JSON_INSERT 新增 保留原值
JSON_REPLACE 不新增 替换

示例:

UPDATE customer_profile
SET profile = JSON_SET(profile, '$.theme', 'dark')
WHERE customer_id = 1;

9.5 JSON_REMOVE()

JSON_REMOVE(document, path [, path] ...)

示例:

UPDATE customer_profile
SET profile = JSON_REMOVE(profile, '$.temporaryToken')
WHERE customer_id = 1;

9.6 JSON_CONTAINS()

JSON_CONTAINS(document, candidate [, path])

示例:

SELECT JSON_CONTAINS(
  '["mysql", "nodejs"]',
  '"mysql"'
);

注意 candidate 本身也必须是合法 JSON 文本。

9.7 JSON 聚合

JSON_ARRAYAGG(expression)
JSON_OBJECTAGG(key, value)

示例:

SELECT JSON_ARRAYAGG(title)
FROM film
WHERE rating = 'G';

JSON 聚合适合生成 API 或报表结构,但大结果会增加 MySQL 的内存、网络和 JSON 解析成本。复杂 API 通常仍应评估由应用层组装是否更清晰。

9.8 其他 JSON 函数

函数 用途
JSON_VALID(value) 判断是否为合法 JSON
JSON_TYPE(value) 返回 JSON 值类型
JSON_LENGTH(value [, path]) 返回数组长度或对象成员数量
JSON_KEYS(object [, path]) 返回对象键数组
JSON_MERGE_PATCH(doc1, doc2, ...) 按 merge-patch 规则合并
JSON_TABLE() 把 JSON 映射成关系表,功能强但语法较复杂

10. 窗口函数

窗口函数从 MySQL 8.0 开始成为日常报表查询的重要能力。下面的函数属于标准 SQL 窗口函数,标记为 [SQL]

窗口函数不会像 GROUP BY 一样把多行压缩成一行,而是在保留明细行的同时计算排名、累计值或相邻行。

通用语法:

window_function(...) OVER (
  [PARTITION BY expression]
  [ORDER BY expression]
  [frame_clause]
)

10.1 ROW_NUMBER():连续行号

ROW_NUMBER() OVER (
  [PARTITION BY expression]
  ORDER BY expression
)

给每个客户的付款按时间编号:

SELECT
  payment_id,
  customer_id,
  payment_date,
  ROW_NUMBER() OVER (
    PARTITION BY customer_id
    ORDER BY payment_date, payment_id
  ) AS payment_number
FROM payment;

10.2 RANK()DENSE_RANK()

RANK() OVER (ORDER BY expression)
DENSE_RANK() OVER (ORDER BY expression)

区别:假设分数为 100、90、90、80

分数 RANK() DENSE_RANK()
100 1 1
90 2 2
90 2 2
80 4 3

10.3 LAG()LEAD():读取前后行

LAG(expression [, offset [, default]]) OVER (...)
LEAD(expression [, offset [, default]]) OVER (...)

比较本次付款和上次付款:

SELECT
  customer_id,
  payment_date,
  amount,
  LAG(amount) OVER (
    PARTITION BY customer_id
    ORDER BY payment_date, payment_id
  ) AS previous_amount
FROM payment;

10.4 聚合函数作为窗口函数

SUMAVGCOUNTMINMAX 可以配合 OVER() 使用。

累计付款金额:

SELECT
  payment_id,
  customer_id,
  payment_date,
  amount,
  SUM(amount) OVER (
    PARTITION BY customer_id
    ORDER BY payment_date, payment_id
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) AS running_total
FROM payment;

经验:窗口函数的 ORDER BY 应尽量具有稳定顺序。如果时间可能相同,再加主键作为第二排序条件。

10.5 其他窗口函数

函数 用途
NTILE(n) 把结果分成 n 组
FIRST_VALUE(value) 窗口中的第一个值
LAST_VALUE(value) 窗口中的最后一个值,特别注意窗口 frame
NTH_VALUE(value, n) 窗口中的第 n 个值
CUME_DIST() 累积分布
PERCENT_RANK() 百分比排名

11. 正则表达式函数

以下函数属于 MySQL 8.0 正则表达式能力,统一标记为 [MySQL]

REGEXP_LIKE(string, pattern [, match_type])
REGEXP_INSTR(string, pattern [, ...])
REGEXP_REPLACE(string, pattern, replacement [, ...])
REGEXP_SUBSTR(string, pattern [, ...])

示例:

SELECT REGEXP_LIKE('user@example.com', '^[^@]+@[^@]+$');
SELECT REGEXP_REPLACE('abc-123', '[0-9]+', 'NUMBER');

正则适合清洗、分析和管理脚本,但不要把复杂接口校验全部推给数据库。正则匹配也通常难以利用普通 B-tree 索引。


12. 系统与连接信息函数

本节同时包含 SQL 标准身份函数和 MySQL 方言函数,具体以每一项的标记为准。

12.1 当前数据库

标记:[MySQL]

DATABASE()
SCHEMA()
SELECT DATABASE();

12.2 当前用户

CURRENT_USERSESSION_USERSYSTEM_USER 是标准 SQL 身份概念,标记为 [SQL];MySQL 同时提供带括号的函数形式,并提供 USER(),后者标记为 [MySQL]

USER()
CURRENT_USER()
SESSION_USER()
SYSTEM_USER()

USER() 更接近客户端连接身份,CURRENT_USER() 表示 MySQL 权限检查实际使用的账号,两者不一定相同。

12.3 MySQL 版本

标记:[MySQL]

VERSION()

12.4 当前连接 ID

标记:[MySQL]

CONNECTION_ID()

排查锁等待和连接问题时可能用到。

12.5 最近自增 ID

标记:[MySQL]

LAST_INSERT_ID()

它是当前连接范围内的状态。使用连接池时,不要先用一个 pool.query() 插入,再用另一个 pool.query() 调用 LAST_INSERT_ID(),因为两次查询可能使用不同连接。

Node.js 使用 mysql2 时,应优先读取写入结果:

const [result] = await pool.execute<ResultSetHeader>(
  "INSERT INTO actor (first_name, last_name) VALUES (?, ?)",
  ["MARY", "SMITH"],
);

console.log(result.insertId);

13. 加密、哈希和编码函数

以下函数标记为 [MySQL]

函数 用途
MD5(string) MD5 摘要,不适合密码安全
SHA1(string) SHA-1 摘要,不适合密码安全
SHA2(string, bits) SHA-2 摘要,如 256、512
AES_ENCRYPT(value, key) AES 加密,密钥管理和模式配置需要谨慎
AES_DECRYPT(value, key) AES 解密
TO_BASE64(value) Base64 编码,不是加密
FROM_BASE64(value) Base64 解码

不要使用 MD5()SHA1() 或单次 SHA2() 保存用户密码。密码应在 Node.js 应用层使用专门的密码哈希算法,例如 Argon2、bcrypt 或 scrypt,并正确设置成本参数和随机盐。


14. 低频但值得认识的函数

14.1 位运算与位函数

标记:[MySQL]

BIT_COUNT(number)

聚合位函数:

BIT_AND(expression)
BIT_OR(expression)
BIT_XOR(expression)

位标记可节省空间,但可读性和可维护性较差,普通业务状态更适合明确字段或关联表。

14.2 UUID

标记:[MySQL]

UUID()
UUID_TO_BIN(uuid [, swap_flag])
BIN_TO_UUID(binary_uuid [, swap_flag])

UUID() 返回文本 UUID。高写入量表如果使用随机 UUID 作为聚簇主键,可能影响索引局部性;需要结合主键设计、存储格式和业务分布式需求评估。

14.3 全文搜索

标记:[MySQL]

MATCH(column1, column2, ...)
AGAINST(search_string [search_modifier])

示例:

SELECT film_id, title
FROM film_text
WHERE MATCH(title, description)
      AGAINST('database' IN NATURAL LANGUAGE MODE);

需要 FULLTEXT 索引。复杂搜索业务通常还要评估 Elasticsearch、OpenSearch 等专用搜索系统。

14.4 空间函数

标记:[MySQL]

常见函数:

ST_GeomFromText()
ST_AsText()
ST_Distance()
ST_Contains()
ST_Within()

只有涉及地图、坐标和空间索引时才需要深入学习。


15. 函数与索引:最重要的性能经验

对索引列套函数可能导致 MySQL 无法直接使用普通索引完成范围查找。

不推荐:

SELECT *
FROM payment
WHERE DATE(payment_date) = '2026-08-09';

推荐:

SELECT *
FROM payment
WHERE payment_date >= '2026-08-09 00:00:00'
  AND payment_date <  '2026-08-10 00:00:00';

不推荐:

WHERE LOWER(email) = 'user@example.com'

更合理的方案可能是:

最终需要使用:

EXPLAIN SELECT ...;

检查真实执行计划,而不是看到函数就断言“一定不走索引”。

16. WHEREHAVING 中使用函数

WHERE 在分组和聚合之前过滤行:

SELECT customer_id, SUM(amount) AS total_amount
FROM payment
WHERE payment_date >= '2005-01-01'
GROUP BY customer_id;

HAVING 在分组之后过滤聚合结果:

SELECT
  customer_id,
  SUM(amount) AS total_amount
FROM payment
GROUP BY customer_id
HAVING SUM(amount) >= 100;

能够在 WHERE 中过滤的原始数据不要全部推迟到 HAVING,尽早减少参与聚合的行通常更高效。

17. NULL 传播规则

SQL 中 NULL 表示未知或缺失,不等于空字符串和数字零。

错误:

WHERE return_date = NULL

正确:

WHERE return_date IS NULL
WHERE return_date IS NOT NULL

多数普通函数接收到 NULL 时会返回 NULL,但并非全部函数都如此。例如:

编写查询时应主动确认函数的 NULL 行为。

18. 高频函数记忆表

目的 优先记忆 标记
统计行数 COUNT(*) [SQL]
求和/平均 SUM()AVG() [SQL]
最大/最小 MAX()MIN() [SQL]
字符串拼接 CONCAT()CONCAT_WS() [MySQL]
字符数/字节数 CHAR_LENGTH() / LENGTH() [SQL] / [MySQL]
去两端空格 TRIM() [SQL]
截取字符串 SUBSTRING() [SQL]
当前时间 CURRENT_TIMESTAMP / NOW() [SQL] / [MySQL]
日期加减 DATE_ADD()DATE_SUB() [MySQL]
日期差 DATEDIFF()TIMESTAMPDIFF() [MySQL]
时间格式化 DATE_FORMAT() [MySQL]
四舍五入 ROUND() [SQL]
空值替代 COALESCE() / IFNULL() [SQL] / [MySQL]
条件判断 CASE / IF() [SQL] / [MySQL]
类型转换 CAST() / CONVERT() [SQL] / [MySQL]
JSON 取值 JSON_EXTRACT()->> [MySQL]
排名 ROW_NUMBER()RANK() [SQL]
前后行 LAG()LEAD() [SQL]

19. 最后建议

学习函数时不要只背名字,至少同时记住四件事:

  1. 参数顺序;
  2. 返回类型;
  3. 遇到 NULL 时的行为;
  4. 是否会影响索引使用。

推荐先熟练掌握:

COUNT / SUM / AVG / MIN / MAX
CONCAT / CHAR_LENGTH / SUBSTRING / TRIM
CURRENT_TIMESTAMP / DATE_ADD / DATEDIFF / TIMESTAMPDIFF
ROUND / CEIL / FLOOR
COALESCE / NULLIF / CASE
CAST
ROW_NUMBER / LAG

然后根据实际项目需要再学习 JSON、正则、空间、全文搜索和加密函数。