MySQL 8.0 常用内置函数用例

MySQL 8.0 常用内置函数用例

文章目录

内容摘要:本文面向使用 MySQL 8.0 的开发者和数据分析人员,按字符串、日期时间、数学、聚合、窗口、条件、JSON、类型转换、系统信息九类整理最常用内置函数。每个条目给出功能、语法、参数、返回值、场景、边界、性能和常见错误,并提供可复制的初始化 SQL 与业务示例。函数行为以 MySQL 8.0 官方手册为依据;由于当前环境未连接可用 MySQL 服务端,示例结果标为"预期结果",需在目标实例复核。空间、全文、正则、加密等低频或专项函数通过官方索引扩展,不在本篇逐条展开。

读者问题、范围与核心结论

这份文档解决什么问题

函数参考最容易变成"名称 + 一行解释"的词典,但真正影响线上结果的是隐式类型转换、NULL 传播、字符集、时区、窗口排序和 JSON 路径。本文的主结论是:选择函数时,先确认输入类型、NULL 语义和是否会破坏索引,再讨论写法是否简短。

覆盖范围与非目标

  • 覆盖 MySQL 8.0 中日常查询、报表、清洗和接口开发最常用的函数;这不是逐项收录全部内置函数的完整手册,同类低频函数在"官方索引"中给出入口。
  • 包括聚合函数和窗口函数;窗口函数自 MySQL 8.0.2 起提供,本文按 MySQL 8.0 通用语义编写。
  • 不把存储函数、用户自定义函数(UDF)、插件函数当作内置函数;空间、全文检索、复制/组复制专用函数仅列官方参考链接。
  • 语法示例以 UTF-8、sql_mode 为常见默认配置为前提;严格模式、时区、排序规则会改变部分结果。

覆盖矩阵

分类 本文逐条覆盖 未逐条展开但可从官方索引扩展的内容
字符串 13 组 正则、编码转换、声音/空间专用字符串函数
日期时间 11 组 周、季度、时区转换及时间间隔构造函数
数学 10 组 对数、三角函数、位运算和随机分布函数
聚合 9 组 方差、标准差、位聚合和精确/近似统计函数
窗口 7 组 窗口聚合的全部变体和帧边界组合
条件 4 组 布尔谓词和表达式运算符
JSON 11 组 JSON Schema、搜索、合并、格式化和高级索引函数
类型转换 4 组 二进制/字符集相关转换细节
系统信息 8 组 UUID、加密摘要、性能模式和复制状态函数

证据边界

结论层次 本文能证明什么 仍需现场确认什么
官方语义 函数签名、参数规则、NULL 传播和版本章节来自 MySQL 8.0 Reference Manual 具体小版本差异、弃用提示
SQL 示例 示例可作为可执行模板;结果按确定性输入推导 目标实例的 sql_mode、字符集、时区和执行计划
性能建议 指出常见索引失效和排序/物化风险 真实数据量、统计信息、硬件和计划,必须用 EXPLAIN ANALYZE 验证

官方总目录:14 Functions and Operators。分类入口:字符串日期时间数学聚合窗口流程控制JSON类型转换信息函数

最小可复现实验集

以下脚本只创建临时实验表,不依赖业务库。重复执行前可先删除表。DECIMAL 用于金额,避免用浮点数验证财务结果。

sql 复制代码
SET NAMES utf8mb4;
DROP TABLE IF EXISTS demo_order;
CREATE TABLE demo_order (
    id BIGINT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    user_name VARCHAR(50) NOT NULL,
    status VARCHAR(20) NOT NULL,
    amount DECIMAL(12, 2) NOT NULL,
    discount DECIMAL(5, 2) NULL,
    tags JSON NULL,
    created_at DATETIME NOT NULL,
    updated_at TIMESTAMP NULL,
    INDEX idx_order_user_created (user_id, created_at),
    INDEX idx_order_status_created (status, created_at)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

INSERT INTO demo_order
    (id, user_id, user_name, status, amount, discount, tags, created_at, updated_at)
VALUES
    (1, 101, '张三', 'PAID',    129.90, 10.00, JSON_ARRAY('vip', 'book'), '2024-01-15 09:30:00', '2024-01-15 09:31:00'),
    (2, 102, '李四', 'PENDING',  88.00, NULL,  JSON_ARRAY('new'),          '2024-02-20 10:00:00', '2024-02-20 10:00:00'),
    (3, 101, '张三', 'PAID',    256.50, 20.00, JSON_ARRAY('vip', 'phone'), '2024-03-01 11:20:00', '2024-03-01 11:21:00'),
    (4, 103, '王五', 'CANCELLED', 50.00, 0.00, NULL,                    '2024-03-05 16:00:00', NULL);
sql 复制代码
-- 检查实例,结果受运行环境影响
SELECT VERSION() AS mysql_version, @@sql_mode AS sql_mode,
       @@time_zone AS session_time_zone, @@character_set_connection AS connection_charset;

预期的确定性结果示例(未在本环境执行):

sql 复制代码
SELECT CONCAT(user_name, ':', status) AS label,
       ROUND(amount * (1 - COALESCE(discount, 0) / 100), 2) AS payable
FROM demo_order
WHERE id = 1;
label payable
张三:PAID 116.91

函数条目如何阅读

每个条目使用同一契约:功能/语法/参数/返回值/场景/边界/性能/错误。其中"版本"只有在官方手册明确有版本条件,或函数在 MySQL 8.0 中存在时才写;"未验证"表示本机没有可用服务端或该行为依赖现场配置。

字符串函数:清洗、拼接与编码

官方参考:String Functions and Operators。字符串位置从 1 开始;长度参数的非整数会按规则取整。

函数 功能、语法与参数 返回值、场景与边界 性能、常见错误、版本
CONCAT CONCAT(str1, str2, ...);参数为任意字符串表达式 返回拼接字符串;任一参数为 NULL 时返回 NULL。适合展示标签。避免把用户输入拼入 SQL。函数在 8.0 可用;结果字符集按参数聚合。 WHERE CONCAT(a,b)=... 上使用会阻断普通索引;可考虑生成列。常见错:误以为 NULL 会当空串。
CONCAT_WS CONCAT_WS(separator, str1, ...);第一个参数是分隔符 用分隔符拼接,后续 NULL 参数被跳过;分隔符为 NULL 时结果为 NULL。适合地址/CSV。空字符串不会被跳过。 大批量拼接会产生临时字符串;注意字符集。8.0 可用。
COALESCE COALESCE(expr1, expr2, ...) 返回第一个非 NULL 值;全部为空返回 NULL。适合默认值和兼容字段。参数类型会参与类型推导。 WHERE COALESCE(index_col, 0)=? 可能无法走索引;优先改写为可索引谓词。8.0 可用。
IFNULL IFNULL(expr1, expr2) expr1 非空返回它,否则返回 expr2。仅二选一。类型转换可能与 COALESCE 不同。 不要用来掩盖数据缺失;金额默认值应显式 DECIMAL。8.0 可用。
LEFT / RIGHT LEFT(str,len)RIGHT(str,len)len 为字符数 截取左右字符;NULL 输入返回 NULL,长度小于 0 返回空串。多字节字符按字符而非字节处理。 WHERE LEFT(code,3)=... 通常不能用前缀索引;可用 LIKE 'abc%' 或生成列。8.0 可用。
SUBSTRING SUBSTRING(str,pos[,len]);位置可为负数 按字符截取;负位置从末尾计算,超界返回空串,NULL 返回 NULL 位置和长度误用字节会切坏中文;大字段截取有内存成本。8.0 可用。
LENGTH / CHAR_LENGTH LENGTH(str) 字节数;CHAR_LENGTH(str) 字符数 UTF-8 中文下二者通常不同;NULL 返回 NULL 校验显示长度必须用 CHAR_LENGTH;协议字节数才用 LENGTH。8.0 可用。
LOWER / UPPER LOWER(str)UPPER(str) 按当前字符集的大小写映射转换;对非字母字符通常不变。 在谓词上包裹列会影响索引;需要大小写不敏感比较时优先选对排序规则。8.0 可用。
TRIM TRIM([remstr FROM] str),也支持 LEADING/TRAILING/BOTH 去除两端空格或指定字符;不是正则替换。 清洗后写回可能改变唯一键;TRIM(col) 查询可能失去索引。8.0 可用。
REPLACE REPLACE(str,from_str,to_str) 替换全部匹配;找不到时原样返回,任一参数 NULL 返回 NULL 不能处理正则;大文本全量扫描。8.0 可用。
FIND_IN_SET FIND_IN_SET(str,strlist) 返回逗号列表中位置,找不到 0,空参数或 NULL 有特殊结果。 不推荐把逗号列表当多值模型;无法有效使用普通索引。8.0 可用。
FORMAT FORMAT(X,D[,locale]) 按 locale 格式化数字并返回字符串;适合展示,不适合继续计算。 结果含千分位,排序会变成字典序。8.0 可用;locale 行为需现场确认。
JSON_QUOTE JSON_QUOTE(string) 将字符串转为合法 JSON 字符串字面量并转义。 不要把已是 JSON 的对象再次 quote;8.0 可用。
sql 复制代码
SELECT user_name,
       CONCAT_WS(' / ', NULLIF(TRIM(user_name), ''), status) AS display_name,
       CHAR_LENGTH(user_name) AS char_count,
       LENGTH(user_name) AS byte_count
FROM demo_order
WHERE id IN (1, 2);

预期:张三 的字符数为 2;在常见 utf8mb4 下字节数为 6。该字节数依连接字符集而变,需在目标实例核对。

日期时间函数:时区、截断与区间

官方参考:Date and Time FunctionsDATETIME 不自动保存时区;TIMESTAMP 会结合会话/系统时区转换显示。

函数 功能、语法与参数 返回值、场景与边界 性能、常见错误、版本
NOW / CURRENT_TIMESTAMP NOW([fsp]) 当前会话时间;同一条语句内通常保持一致。 不适合跨服务唯一时间戳;测试需注入时钟。8.0 可用。
CURDATE / CURRENT_DATE CURDATE() 当前日期。 与服务器时区相关;不要用字符串比较日期。8.0 可用。
DATE / TIME DATE(expr)TIME(expr) 提取日期或时间部分;非法值可能返回 NULL/警告,严格模式行为不同。 WHERE DATE(created_at)=? 常使索引失效;改用半开区间。8.0 可用。
DATE_ADD / DATE_SUB DATE_ADD(date, INTERVAL expr unit) 日期加减;月末、闰年会按日历规则调整。 单位必须是合法关键字;跨 DST 时不要把天等同 24 小时。8.0 可用。
DATEDIFF DATEDIFF(expr1,expr2) 返回日期部分相差天数,忽略时间。 需要精确时长应使用 TIMESTAMPDIFF;8.0 可用。
TIMESTAMPDIFF TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2) 按单位返回整数差值,截断小数单位。 单位选择会影响结果(MONTH 不是固定 30 天);8.0 可用。
DATE_FORMAT DATE_FORMAT(date,format) 按格式返回字符串,如 %Y-%m-%d 只用于展示/分组标签;不要对结果再做日期比较。8.0 可用。
STR_TO_DATE STR_TO_DATE(str,format) 按格式解析字符串为日期时间;不匹配返回 NULL 或警告。 输入校验应在边界层完成;格式符错误是常见原因。8.0 可用。
EXTRACT EXTRACT(unit FROM date) 提取年、月、日、小时等数值部分。 同样可能破坏索引;8.0 可用。
LAST_DAY LAST_DAY(date) 返回月份最后一天;无效日期返回 NULL 可用于账期边界;注意 DATETIME 结果被截为日期。8.0 可用。
UNIX_TIMESTAMP / FROM_UNIXTIME UNIX_TIMESTAMP([date])FROM_UNIXTIME(unix_timestamp[,format]) 在日期与 Unix 秒之间转换;受时区影响。 2038、时区、毫秒单位是常见坑;毫秒输入需先除以 1000。8.0 可用。

推荐的可索引时间范围写法:

sql 复制代码
SELECT id, created_at
FROM demo_order
WHERE created_at >= '2024-03-01 00:00:00'
  AND created_at <  '2024-04-01 00:00:00';

不要写成 WHERE DATE(created_at) = '2024-03-01',除非已用生成列/函数索引并验证执行计划。

数学函数:数值计算与舍入规则

官方参考:Mathematical Functions。除非另有说明,NULL 输入通常返回 NULL;溢出、非法转换和除零受 sql_mode 影响。

函数 功能、语法与参数 返回值、场景与边界 性能、常见错误、版本
ABS ABS(X) 绝对值;最小有符号整数取绝对值可能溢出。 金额先确认 DECIMAL;8.0 可用。
ROUND ROUND(X[,D]) 按位数四舍五入;D 可为负数。精确值与近似值舍入细节不同。 仅展示时不要提前舍入;金额规则应由业务确认。8.0 可用。
TRUNCATE TRUNCATE(X,D) 截断而非四舍五入;D 为负数可截断整数位。 不要把它当财务舍入;8.0 可用。
CEIL / CEILING CEIL(X) 向上取整。 负数结果与直觉不同;8.0 可用。
FLOOR FLOOR(X) 向下取整。 负数向更小方向取整;8.0 可用。
MOD MOD(N,M)N % M 取模;除数为 0 时返回 NULL 分页/分桶前校验除数;8.0 可用。
POWER / POW POWER(X,Y) 幂运算,可能返回近似数或溢出。 科学计算需控制精度;8.0 可用。
SQRT SQRT(X) 非负平方根;负数返回 NULL 先校验域;8.0 可用。
RAND RAND([seed]) 伪随机数;无 seed 时每次调用可能不同。 ORDER BY RAND() 会全表计算和排序,不适合大表抽样。8.0 可用。
SIGN SIGN(X) 负数 -1、0 为 0、正数 1。 IF 更适合分类;8.0 可用。
sql 复制代码
SELECT amount,
       ROUND(amount * (1 - COALESCE(discount, 0) / 100), 2) AS payable,
       CEIL(amount) AS upper_amount,
       MOD(id, 2) AS bucket
FROM demo_order;

聚合函数:从明细到统计结果

官方参考:Aggregate Function Descriptions。聚合会忽略大多数 NULL 值;空集合下 COUNT 返回 0,SUM/AVG 等通常返回 NULL

函数 功能、语法与参数 返回值、场景与边界 性能、常见错误、版本
COUNT(*) COUNT(*) 行数,不因列为 NULL 而减少。 统计存在性优先用 COUNT(*);8.0 可用。
COUNT(expr) COUNT(expr) 统计表达式非 NULL 的行。 COUNT(*) 混淆会少算;8.0 可用。
COUNT(DISTINCT expr) 去重后计数;多列写法需确认版本/语义 返回非空唯一值数量;大基数可能使用临时表。 先评估内存和索引;8.0 可用。
SUM SUM([DISTINCT] expr) 求和;无行或全空通常为 NULL 金额用 DECIMAL;溢出需关注类型范围。8.0 可用。
AVG AVG([DISTINCT] expr) 平均值;等价于 SUM/COUNT 的语义组合。 分母为 0 时结果 NULL;8.0 可用。
MIN / MAX MIN(expr)MAX(expr) 最小/最大非空值;字符串按排序规则比较。 字符串排序规则会影响结果;8.0 可用。
GROUP_CONCAT GROUP_CONCAT([DISTINCT] expr ORDER BY ... SEPARATOR str) 将组内值拼成字符串;受 group_concat_max_len 限制,可能截断。 不用于传输结构化数据;需要 JSON 时用 JSON_ARRAYAGG。8.0 可用。
JSON_ARRAYAGG JSON_ARRAYAGG(col_or_expr) 聚合为 JSON 数组;顺序未指定,不能依赖自然顺序。 结果可能很大;8.0.14 起支持窗口形式。
JSON_OBJECTAGG JSON_OBJECTAGG(key,value) 聚合为 JSON 对象;键为 NULL 会报错,重复键通常由后值覆盖前值,但输入顺序未定义时不能依赖最终覆盖结果。 先确保键唯一;8.0.14 起支持窗口形式。
sql 复制代码
SELECT status,
       COUNT(*) AS order_count,
       COALESCE(SUM(amount), 0.00) AS gross_amount,
       AVG(amount) AS average_amount,
       GROUP_CONCAT(id ORDER BY id SEPARATOR ',') AS order_ids
FROM demo_order
GROUP BY status;

预期分组行数:PAID=2PENDING=1CANCELLED=1;金额结果按 DECIMAL 计算,具体格式以客户端显示为准。

窗口函数:保留明细的排名、累计与分组计算

官方参考:Window Function Descriptions。窗口函数在不折叠明细行的前提下计算分组统计;ORDER BY 决定顺序,未指定稳定排序时并列行顺序不可依赖。

函数 功能、语法与参数 返回值、场景与边界 性能、常见错误、版本
ROW_NUMBER ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) 每个分区从 1 开始的唯一序号;并列也会被打散。 分页需使用稳定唯一键作为次排序;MySQL 8.0.2+。
RANK RANK() OVER (...) 并列同名次,后续名次跳跃。 竞赛排名适用;MySQL 8.0.2+。
DENSE_RANK DENSE_RANK() OVER (...) 并列同名次,后续名次不跳跃。 分层统计适用;MySQL 8.0.2+。
LAG / LEAD LAG(expr[,N[,default]]) OVER (...) 访问前/后 N 行;越界返回默认值或 NULL 必须指定合理排序;MySQL 8.0.2+。
FIRST_VALUE / LAST_VALUE FIRST_VALUE(expr) OVER (...) 取窗口帧首/尾值;默认帧可能使 LAST_VALUE 只看到当前行。 使用 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 明确全分区;MySQL 8.0.2+。
NTILE NTILE(N) OVER (...) 将分区尽量平均分为 N 桶。 N 必须为正整数;MySQL 8.0.2+。
CUME_DIST / PERCENT_RANK CUME_DIST() OVER (...)PERCENT_RANK() OVER (...) 计算累计分布/百分比排名。 小样本边界值容易误读;MySQL 8.0.2+。
sql 复制代码
SELECT id, user_id, amount,
       ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at, id) AS seq,
       SUM(amount) OVER (
           PARTITION BY user_id
           ORDER BY created_at, id
           ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
       ) AS running_amount,
       LAG(amount) OVER (PARTITION BY user_id ORDER BY created_at, id) AS previous_amount
FROM demo_order;

常见错误是把窗口函数直接写进 WHERE;应先放在派生表/CTE,再在外层过滤:

sql 复制代码
WITH ranked AS (
    SELECT d.*, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at, id) AS rn
    FROM demo_order AS d
)
SELECT * FROM ranked WHERE rn = 1;

条件函数:分支、空值与短路假设

官方参考:Flow Control Functions。不要把"看起来只会执行一个分支"当作可移植的副作用控制机制;表达式类型推导和优化器行为需实测。

函数 功能、语法与参数 返回值、场景与边界 性能、常见错误、版本
IF IF(condition, true_expr, false_expr) 条件真/假返回不同表达式;NULL 条件按非真处理。 复杂逻辑可读性差,优先 CASE;8.0 可用。
CASE CASE WHEN cond THEN expr [WHEN ...] [ELSE expr] END 或简单 CASE 返回首个满足条件的分支;无匹配且无 ELSE 返回 NULL 分支类型需兼容;不要遗漏 ELSE。8.0 可用。
NULLIF NULLIF(expr1,expr2) 相等返回 NULL,否则返回 expr1 常用于防止除零:a / NULLIF(b,0);8.0 可用。
IFNULL 见字符串章节 二选一默认值;类型推导需确认。 COALESCE 的多参数能力不同;8.0 可用。
sql 复制代码
SELECT id, status,
       CASE status
           WHEN 'PAID' THEN '已支付'
           WHEN 'PENDING' THEN '待支付'
           WHEN 'CANCELLED' THEN '已取消'
           ELSE '未知'
       END AS status_label,
       amount / NULLIF(discount, 0) AS amount_per_discount
FROM demo_order;

JSON 函数:路径、抽取与修改

官方参考:JSON Function Reference。JSON 路径使用 $ 根、. 成员和 [N] 数组下标;不存在路径通常得到 NULL 或 0/1,需按函数语义判断。

函数 功能、语法与参数 返回值、场景与边界 性能、常见错误、版本
JSON_EXTRACT / -> JSON_EXTRACT(json_doc,path[,path...])col->'$.a' 是简写 返回 JSON 值;多路径返回数组;不存在路径返回 NULL 结果仍是 JSON,字符串可能带引号;8.0 可用。
->> col->>'$.a' 等价于 JSON_UNQUOTE(JSON_EXTRACT(...)),返回未加引号文本。 -> 混用会导致比较失败;8.0 可用。
JSON_UNQUOTE JSON_UNQUOTE(json_val) 去掉 JSON 字符串引号并处理转义;非字符串 JSON 原样返回。 不要对普通 SQL 字符串误用;8.0 可用。
JSON_CONTAINS JSON_CONTAINS(target,candidate[,path]) 包含返回 1,否则 0;对象比较是键值语义。 路径错误或文档非法会报错;8.0 可用。
JSON_CONTAINS_PATH JSON_CONTAINS_PATH(json_doc,one_or_all,path...) 判断路径是否存在,返回 1/0。 oneall 语义不同;8.0 可用。
JSON_SET JSON_SET(json_doc,path,val[,path,val]...) 存在则更新,不存在则添加。 更新大 JSON 会重写文档;8.0 可用。
JSON_INSERT JSON_INSERT(json_doc,path,val,...) 只插入不存在路径,已有值不覆盖。 JSON_SET 混淆会产生静默不更新;8.0 可用。
JSON_REPLACE JSON_REPLACE(json_doc,path,val,...) 只替换已存在路径,不新增。 需要判断是否成功时同时用 JSON_CONTAINS_PATH;8.0 可用。
JSON_REMOVE JSON_REMOVE(json_doc,path,...) 删除指定路径。 路径不存在通常不报错;8.0 可用。
JSON_ARRAY / JSON_OBJECT JSON_ARRAY(val,...)JSON_OBJECT(key,val,...) 构造 JSON 数组/对象;对象键不能为 NULL 值类型由 SQL 类型决定;8.0 可用。
JSON_TABLE JSON_TABLE(expr,path COLUMNS(...)) 将 JSON 展开为关系表;需定义列路径、类型和错误处理。 可能产生大量行;先限制文档规模。8.0.4+。
sql 复制代码
SELECT id,
       user_name,
       tags->>'$[0]' AS first_tag,
       JSON_CONTAINS(tags, JSON_QUOTE('vip')) AS is_vip,
       JSON_SET(COALESCE(tags, JSON_ARRAY()), '$[2]', 'featured') AS enriched_tags
FROM demo_order;

可索引场景优先建立生成列或多值索引(多值索引依赖 InnoDB 与目标 8.0 小版本,且只能用于数组等特定 JSON 结构),不要在高选择性查询中反复对整列 JSON 解析。

类型转换函数:显式优于隐式

官方参考:Cast Functions and Operators。隐式转换可能产生警告、截断或索引失效;接口边界和比较条件尽量显式转换。

函数 功能、语法与参数 返回值、场景与边界 性能、常见错误、版本
CAST CAST(expr AS type);常见类型 CHARDATEDATETIMEDECIMALSIGNEDUNSIGNEDJSON 转为目标类型;非法值在严格模式下可能报错,否则可能产生警告/截断。 对索引列 CAST 常使索引失效;优先转换参数。8.0 可用。
CONVERT CONVERT(expr, type)CONVERT(expr USING charset) 类型或字符集转换;与 CAST 功能重叠。 字符集转换可能丢失字符;8.0 可用。
BINARY BINARY expr 将表达式按二进制字符串比较,影响大小写和排序。 可能改变索引使用与排序结果;优先设置正确排序规则。8.0 可用。
HEX / UNHEX HEX(str)UNHEX(hex_str) 二进制与十六进制字符串互转;奇数/非法十六进制有边界行为。 仅用于编码展示或传输,不能当加密;8.0 可用。
sql 复制代码
SELECT CAST('2024-03-01' AS DATE) AS d,
       CAST('12.50' AS DECIMAL(10,2)) AS n,
       CONVERT('abc' USING utf8mb4) AS text_value;

系统信息函数:诊断而非业务数据

官方参考:Information Functions。这些函数反映当前连接、会话或实例状态;不要把连接 ID、版本号等动态信息持久化为业务事实。

函数 功能、语法与参数 返回值、场景与边界 性能、常见错误、版本
VERSION VERSION() 返回服务器版本字符串,可能带发行信息。 用于诊断/能力探测,不要硬编码字符串比较;8.0 可用。
DATABASE / SCHEMA DATABASE()SCHEMA() 当前默认数据库;未选择数据库返回 NULL 连接池复用时不要假设默认库;8.0 可用。
USER / CURRENT_USER USER() 返回客户端认证用户;CURRENT_USER() 返回授权账户 二者可能不同,后者用于权限判断。 审计应记录服务端认证结果;8.0 可用。
CONNECTION_ID CONNECTION_ID() 当前连接 ID。 只适合诊断和杀会话;不能作业务主键。8.0 可用。
LAST_INSERT_ID LAST_INSERT_ID([expr]) 无参取最近自增值;带参会设置会话值。 并发连接隔离;不要跨连接读取。8.0 可用。
ROW_COUNT ROW_COUNT() 返回上一条语句影响行数;对 SELECT 等语句语义不同。 必须紧接目标语句调用;8.0 可用。
FOUND_ROWS FOUND_ROWS() SQL_CALC_FOUND_ROWS 相关;SQL_CALC_FOUND_ROWSFOUND_ROWS() 自 MySQL 8.0.17 起弃用。 分页应使用独立 COUNT(*) 或窗口策略;预计未来版本移除,不建议新代码使用。
ISNULL ISNULL(expr) 为空返回 1,否则 0。 expr IS NULL 等价表达式相比可读性按团队规范选择;8.0 可用。

相近函数对比:避免"能跑但语义错"

补充常用函数索引

下表补上正文主表未逐项展开、但在日常开发中仍较常见的函数。它们遵循同样的核对原则:先看官方语义,再用目标实例验证边界和执行计划。

分类 函数 用途与关键边界 官方入口
字符串 ASCIILOCATEINSTRLPADRPADREVERSEREPEATSTRCMP 字符编码、查找、填充、反转、重复和字典序比较;长度、空串、字符集会影响结果 字符串函数
日期时间 YEARMONTHDAYQUARTERWEEKWEEKDAYDAYOFWEEKCONVERT_TZ 提取日历字段、周计算和时区转换;周模式、时区表加载和夏令时必须现场确认 日期时间函数
数学 LOGLOG10EXPPISINCOSTAN 对数、指数和三角计算;输入定义域、近似值和溢出是主要边界 数学函数
聚合 STDDEV_POPSTDDEV_SAMPVAR_POPVAR_SAMPBIT_ANDBIT_ORBIT_XOR 离散统计与位聚合;空集合、样本量和无符号位宽需单独测试 聚合函数
条件 GREATESTLEAST 返回多个表达式的最大/最小值;任一参数为 NULL 时通常传播 NULL,混合类型需注意转换 流程控制函数
JSON JSON_DEPTHJSON_KEYSJSON_LENGTHJSON_PRETTYJSON_SEARCHJSON_VALUEJSON_OVERLAPS JSON 结构分析、搜索、标量提取与重叠判断;路径、返回类型、错误处理和版本差异需核对 JSON 函数
标识/摘要 UUIDUUID_TO_BINBIN_TO_UUIDMD5SHA2 UUID 生成/转换和摘要计算;摘要不是密码存储方案,UUID 排序与字节序参数需保持一致 信息函数加密函数

以上函数未在本文逐个给出完整结果表,原因是部分行为依赖字符集、周模式、时区表、输入定义域或实例配置;扩展时应复制本文的函数条目模板,而不是只添加名称。

对比 关键差异 选择建议
IFNULL vs COALESCE 前者固定两个参数;后者按从左到右取首个非空值,且遵循标准 SQL 只有二选一用 IFNULL;需要多个候选或跨数据库兼容用 COALESCE
IF vs CASE IF 是 MySQL 专用三参数函数;CASE 可多分支并更易表达业务规则 简单二分可用 IF;多状态、需迁移或需审计时用 CASE
ROUND vs TRUNCATE ROUND 四舍五入;TRUNCATE 直接截断 财务规则先确认舍入方式;展示层不要改变存储值。
LENGTH vs CHAR_LENGTH 字节数 vs 字符数 协议/存储容量用 LENGTH;用户可见长度用 CHAR_LENGTH
DATEDIFF vs TIMESTAMPDIFF 前者只算日期天数;后者可指定单位并考虑时间部分 账期天数用 DATEDIFF;年龄、分钟、月份差用 TIMESTAMPDIFF
COUNT(*) vs COUNT(col) 前者统计行;后者忽略列为 NULL 的行 统计行数用 COUNT(*);统计非空值才用 COUNT(col)
GROUP_CONCAT vs JSON_ARRAYAGG 前者文本拼接且长度受配置限制;后者结构化 JSON 给人看或兼容旧接口用前者;下游程序消费用后者。
-> vs ->> 前者返回 JSON 值;后者返回去引号文本 继续 JSON 运算用 ->;与 SQL 文本比较/展示用 ->>
JSON_SET vs JSON_INSERT vs JSON_REPLACE 更新并可新增;只新增;只更新 根据"字段不存在时是否创建"明确选择,避免静默数据错误。

逐函数最小 Demo 速查

下面的语句为前述条目的最小可执行调用;它们用于确认返回类型和边界,不替代业务数据测试。结果中带当前时间、随机数、实例信息或排序的语句,不给出固定快照。

sql 复制代码
-- 字符串
SELECT ASCII('A'), CHAR_LENGTH('中文'), LENGTH('中文'),
       LOWER('AbC'), UPPER('AbC'), LEFT('abcdef', 2), RIGHT('abcdef', 2),
       SUBSTRING('abcdef', 2, 3), TRIM('  x  '), REPLACE('a-b', '-', '_'),
       CONCAT('a', 'b'), CONCAT_WS('-', 'a', NULL, 'b'),
       COALESCE(NULL, NULL, 'fallback'), IFNULL(NULL, 'fallback'),
       FIND_IN_SET('b', 'a,b,c'), FORMAT(12345.6, 2), JSON_QUOTE('a"b');

-- 日期时间
SELECT NOW(), CURRENT_TIMESTAMP, CURDATE(), CURRENT_DATE,
       DATE('2024-03-01 12:30:00'), TIME('2024-03-01 12:30:00'),
       DATE_ADD('2024-01-31', INTERVAL 1 MONTH),
       DATE_SUB('2024-03-01', INTERVAL 1 DAY),
       DATEDIFF('2024-03-05', '2024-03-01'),
       TIMESTAMPDIFF(HOUR, '2024-03-01 00:00:00', '2024-03-01 03:30:00'),
       DATE_FORMAT('2024-03-01', '%Y-%m'),
       STR_TO_DATE('2024/03/01', '%Y/%m/%d'),
       EXTRACT(YEAR FROM '2024-03-01'), LAST_DAY('2024-02-01'),
       FROM_UNIXTIME(1709251200), UNIX_TIMESTAMP('2024-03-01 00:00:00');

-- 数学
SELECT ABS(-3), ROUND(12.345, 2), TRUNCATE(12.345, 2),
       CEIL(2.1), CEILING(2.1), FLOOR(2.9), MOD(10, 3),
       POWER(2, 3), SQRT(9), SIGN(-8), RAND(7);

-- 聚合
SELECT COUNT(*), COUNT(discount), COUNT(DISTINCT user_id),
       SUM(amount), AVG(amount), MIN(amount), MAX(amount),
       GROUP_CONCAT(id ORDER BY id), JSON_ARRAYAGG(id),
       JSON_OBJECTAGG(id, status)
FROM demo_order;

-- 条件与类型转换
SELECT IF(amount > 100, '大额', '普通'),
       CASE status WHEN 'PAID' THEN '已支付' ELSE '其他' END,
       NULLIF(discount, 0),
       CAST('12.50' AS DECIMAL(10,2)), CONVERT('12' , SIGNED),
       CONVERT('中文' USING utf8mb4), BINARY 'Ab' = BINARY 'ab',
       HEX('A'), UNHEX('41')
FROM demo_order WHERE id = 1;

-- JSON 与系统信息
SELECT tags->'$[0]', tags->>'$[0]', JSON_EXTRACT(tags, '$[0]'),
       JSON_UNQUOTE(JSON_QUOTE('x')), JSON_CONTAINS(tags, JSON_QUOTE('vip')),
       JSON_CONTAINS_PATH(tags, 'one', '$[0]'),
       JSON_SET(COALESCE(tags, JSON_ARRAY()), '$[1]', 'x'),
       JSON_INSERT(COALESCE(tags, JSON_ARRAY()), '$[1]', 'x'),
       JSON_REPLACE(COALESCE(tags, JSON_ARRAY()), '$[0]', 'x'),
       JSON_REMOVE(COALESCE(tags, JSON_ARRAY()), '$[0]'),
       JSON_ARRAY('a', 1), JSON_OBJECT('k', 1),
       VERSION(), DATABASE(), SCHEMA(), USER(), CURRENT_USER(), CONNECTION_ID(),
       LAST_INSERT_ID(), ROW_COUNT(), ISNULL(discount)
FROM demo_order WHERE id = 1;
sql 复制代码
-- 窗口函数:同一条语句保留明细行
SELECT id, user_id, amount,
       ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at, id) AS rn,
       RANK() OVER (PARTITION BY user_id ORDER BY amount DESC, id) AS rnk,
       DENSE_RANK() OVER (PARTITION BY user_id ORDER BY amount DESC, id) AS dense_rnk,
       LAG(amount, 1, 0) OVER (PARTITION BY user_id ORDER BY created_at, id) AS prev_amount,
       LEAD(amount, 1, 0) OVER (PARTITION BY user_id ORDER BY created_at, id) AS next_amount,
       FIRST_VALUE(amount) OVER (
           PARTITION BY user_id ORDER BY created_at, id
           ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
       ) AS first_amount,
       LAST_VALUE(amount) OVER (
           PARTITION BY user_id ORDER BY created_at, id
           ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
       ) AS last_amount,
       NTILE(2) OVER (ORDER BY amount DESC, id) AS bucket,
       CUME_DIST() OVER (ORDER BY amount) AS cume_dist_value,
       PERCENT_RANK() OVER (ORDER BY amount) AS percent_rank_value
FROM demo_order;

JSON_TABLE 需要表值展开,示例单独写出以突出列契约:

sql 复制代码
SELECT jt.tag
FROM demo_order AS d,
     JSON_TABLE(d.tags, '$[*]' COLUMNS(tag VARCHAR(20) PATH '$')) AS jt
WHERE d.id = 1;

预期 JSON_TABLE 返回 vipbook 两行;若 tags 为 SQL NULL 或 JSON null,不要与"路径不存在"混淆。JSON null 行为在 MySQL 8.0.21 有调整,必须在目标小版本验证。

失败路径、边界与排错清单

NULL 传播

sql 复制代码
SELECT CONCAT('金额=', NULL) AS concat_result,
       COALESCE(NULL, 0) AS coalesce_result,
       COUNT(discount) AS non_null_discount_count,
       COUNT(*) AS row_count
FROM demo_order;

预期:CONCAT 结果为 NULLCOALESCE 为 0,COUNT(discount) 小于 COUNT(*)。若结果不同,先检查表达式和数据,而不是先改函数。

日期谓词不走索引

sql 复制代码
EXPLAIN ANALYZE
SELECT * FROM demo_order WHERE DATE(created_at) = '2024-03-01';

EXPLAIN ANALYZE
SELECT * FROM demo_order
WHERE created_at >= '2024-03-01 00:00:00'
  AND created_at <  '2024-03-02 00:00:00';

第二种写法通常更利于使用 created_at 索引,但"通常"不是保证;必须在目标数据量和统计信息上验证。

类型和字符集错误

  • ERROR 1292 或截断警告:检查字符串日期、数字转换和 sql_mode
  • 中文长度不符合预期:同时查看 CHAR_LENGTHLENGTH、连接字符集和列字符集。
  • 金额出现 0.1 + 0.2 类似精度问题:检查是否使用了 DOUBLE/FLOAT,财务列改用 DECIMAL

窗口函数结果不稳定

排名、分页和 LAG 必须提供能唯一确定顺序的键,例如 ORDER BY created_at, id。只有时间字段时,同一时间的行顺序未定义。

JSON 路径为空

先用 JSON_VALIDJSON_TYPEJSON_CONTAINS_PATH 区分"文档非法""路径不存在""值为 JSON null"三种情况,不要仅凭客户端显示的 NULL 判断。

函数对索引与执行计划的影响

函数放在索引列上,常会让优化器无法直接使用普通 B-Tree 索引。下面是"风险模式 → 常见改写"的对照;"通常"不等于保证,最终结论必须以目标实例的 EXPLAINEXPLAIN ANALYZE 为准。

风险写法 常见改写 仍需验证
WHERE DATE(created_at) = '2024-03-01' created_at >= '2024-03-01' AND created_at < '2024-03-02' 时区、边界、索引选择
WHERE LOWER(user_name) = 'zhangsan' 使用合适排序规则,或建立生成列/函数索引 排序规则与唯一性
WHERE CAST(order_no AS CHAR) = '1001' 让参数转换为列的真实类型 隐式转换警告
WHERE JSON_EXTRACT(tags, '$[0]') = 'vip' 生成列、JSON 索引或多值索引 8.0 小版本与数据分布
WHERE CONCAT(code, region) = 'A-1' 拆成可索引列条件,或建立生成列 组合键语义

EXPLAIN ANALYZE 需要 MySQL 8.0.18 及以上;更早的 8.0 版本使用 EXPLAIN,不能把命令直接复制到所有 8.0 实例。完整实验脚本见 mysql-8函数参考-实验脚本.sql

验证步骤与证据记录

在隔离 MySQL 8.0 实例上执行。以下是 mysql 客户端命令和 SQL 的混合示意SOURCE 不是服务端 SQL,<代表性查询> 必须替换为真实语句:

sql 复制代码
SELECT VERSION(), @@sql_mode, @@time_zone,
       @@character_set_connection, @@collation_connection;
SHOW WARNINGS;

mysql 客户端命令:

text 复制代码
SOURCE /path/to/mysql-8函数参考-实验脚本.sql

MySQL 8.0.18+ 的 SQL 示例:

sql 复制代码
EXPLAIN ANALYZE
SELECT * FROM demo_order
WHERE created_at >= '2024-03-01 00:00:00'
  AND created_at <  '2024-03-02 00:00:00';

验证记录应至少包含:

  1. 实例版本、小版本、存储引擎、字符集、排序规则和时区;
  2. 每类至少一个 NULL、空集合、非法输入和边界值用例;
  3. 关键查询的 EXPLAIN/EXPLAIN ANALYZE,不能用函数名称推断索引一定生效;
  4. 结果集截图或导出文件,确保客户端没有自动格式化或时区转换;
  5. 对失败 SQL 记录错误码、警告和 sql_mode

当前已证明:本文的函数签名、分类和注意事项有 MySQL 8.0 官方手册链接支撑;示例 SQL 语法按 MySQL 8.0 书写。当前未证明:本机真实服务端执行、生产数据性能、特定 8.0 小版本的全部兼容性,以及业务时区/权限配置下的最终结果。

取舍与维护建议

  • "所有常用函数"比"所有函数"更适合团队手册;若要做完整参考,应以官方目录为索引,按低频类别拆分文档。
  • 示例追求可复制,但不把一条示例外推为生产性能结论;涉及索引、窗口排序、JSON 大文档时必须补执行计划和数据规模。
  • 将展示格式(DATE_FORMATFORMAT)与业务值计算分开,避免把字符串写回数值/日期列。
  • NULL 语义写进接口契约:默认值是 0、空串还是保持 NULL,必须由业务决定。
  • MySQL 升级时重跑本页"验证步骤",特别是弃用函数、JSON_TABLE、窗口函数和 SQL 模式相关行为。

结论

这份参考文档覆盖 MySQL 8.0 日常开发最常用的九类内置函数,并把语法之外的 NULL、类型、时区、字符集、窗口顺序、JSON 路径和索引边界纳入同一套检查。可以直接用最小实验集开始验证;在连接真实实例前,不应把示例预期结果或性能建议当成生产验收结论。

附录:官方完整索引与扩展阅读

相关推荐
ZGG0031 小时前
MySQL 索引详解:B+ 树、聚簇索引与最左前缀
java·数据库·mysql
勿忘,瞬间1 小时前
Mybatis高阶
java·数据库·mybatis
运维行者_2 小时前
ISP 企业级带宽计费怎么做?网络流量计费的 6 大核心能力
运维·服务器·网络·数据库·支持向量机·接口隔离原则
奇树谦2 小时前
PCB生产制造全流程详解:从开料、钻孔、沉铜到检测、包装
网络·数据库·制造
驾驭人生2 小时前
Hangfire.Redis.StackExchange 已归档停更!生产任务卡死、重复执行、网络抖动问题解决方案
数据库·redis·缓存
xierui1231232 小时前
Agent记忆不是聊天记录:用三层存储构建可追溯的 AI 工作流
数据库·人工智能·aigc·软件工程
2301_800074213 小时前
mysql DQL
数据库·sql·mysql
西风未眠3 小时前
ClickHouse数据库引擎引起的数据丢失
数据库·clickhouse·故障
海浪仙人掌3 小时前
应收账款分析如何操作?应收账款分析有哪些注意事项?
数据库·人工智能