MySQL 提供了海量的内置函数,熟练运用这些函数可以让我们在数据处理、字符串操作、日期计算、统计分析等场景下事半功倍。本文将系统梳理 MySQL 8.0 中所有常用内置函数,涵盖聚合函数、字符串函数、日期时间函数、窗口函数、数学函数、JSON函数、加密函数、信息函数、类型转换函数等,并为每个函数提供语法说明和使用示例。

环境说明:本文示例基于 MySQL 8.0 版本,MySQL 8.0 引入了窗口函数、JSON_TABLE 等大量新特性,建议使用 8.0 及以上版本以获得完整函数支持。
聚合函数对一组值执行计算,返回单个汇总值,常与 GROUP BY 子句配合使用。
| 函数名 | 说明 | 语法 |
|---|---|---|
COUNT() | 统计行数 | COUNT([DISTINCT] expr) |
SUM() | 求和 | SUM([DISTINCT] expr) |
AVG() | 求平均值 | AVG([DISTINCT] expr) |
MAX() | 返回最大值 | MAX(expr) |
MIN() | 返回最小值 | MIN(expr) |
示例 1 — 基础统计:
-- 假设有一张 products 表-- 总产品数SELECT COUNT(*) AS total_products FROM products;-- 有效库存记录数(stock 列非 NULL)SELECT COUNT(stock) AS stock_count FROM products;-- 不同类别的数量SELECT COUNT(DISTINCT category) AS category_count FROM products;-- 总库存SELECT SUM(stock) AS total_stock FROM products;-- 平均价格SELECT AVG(price) AS avg_price FROM products;-- 最高价格SELECT MAX(price) AS max_price FROM products;-- 最低价格SELECT MIN(price) AS min_price FROM products;
生产环境中经常混淆 COUNT 的不同用法,它们的区别如下:
COUNT(1):统计所有行数,不受字段定义影响。相当于增加一个常量列,统计有多少个 1。
COUNT(*):统计所有行数,包括 NULL 行。
COUNT(字段):统计指定字段不为 NULL 的行数。
COUNT(DISTINCT 字段):统计指定字段去重且不为 NULL 的行数。
-- 示例对比SELECT COUNT(1) AS all_rows, -- 所有行 COUNT(*) AS all_rows_too, -- 所有行(同上) COUNT(email) AS has_email, -- 邮件不为空的行 COUNT(DISTINCT department) AS dept_count -- 部门数量FROM employees;
使用建议:表中存在主键或索引时使用
COUNT(主键字段)或COUNT(索引字段);表中无主键时使用COUNT(1)优于COUNT(*)。
| 函数名 | 说明 | 语法 |
|---|---|---|
GROUP_CONCAT() | 将分组中的值连接成一个字符串 | GROUP_CONCAT([DISTINCT] expr [ORDER BY ...] [SEPARATOR 'str']) |
BIT_AND() | 按位与 | BIT_AND(expr) |
BIT_OR() | 按位或 | BIT_OR(expr) |
BIT_XOR() | 按位异或 | BIT_XOR(expr) |
示例 2 — GROUP_CONCAT 行转列:
-- 将每个部门的人员姓名合并SELECT department, GROUP_CONCAT(name ORDER BY name SEPARATOR ', ') AS membersFROM employeesGROUP BY department;-- 结果类似:IT | Alice, Bob, Charlie
示例 3 — JSON 聚合(MySQL 8.0 新增):
-- 将分组数据聚合为 JSON 数组SELECT department, JSON_ARRAYAGG(name) AS names FROM employees GROUP BY department;-- 将分组数据聚合为 JSON 对象SELECT department, JSON_OBJECTAGG(emp_id, name) AS emp_map FROM employees GROUP BY department;
| 函数名 | 说明 | 语法 |
|---|---|---|
CONCAT() | 拼接字符串 | CONCAT(str1, str2, ...) |
CONCAT_WS() | 用分隔符拼接 | CONCAT_WS(separator, str1, str2, ...) |
SUBSTRING() / SUBSTR() | 截取子字符串 | SUBSTRING(str, pos [, len]) |
LEFT() | 左侧截取 | LEFT(str, len) |
RIGHT() | 右侧截取 | RIGHT(str, len) |
示例 4:
-- 拼接姓名SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;-- 结果:Alice Smith-- 用分隔符拼接SELECT CONCAT_WS('-', '2024', '01', '15') AS date_str;-- 结果:2024-01-15-- 截取子字符串(pos 从 1 开始)SELECT SUBSTRING('Hello World', 1, 5) AS result;-- 结果:Hello-- 手机号脱敏SELECT CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4)) AS masked_phone FROM users;-- 结果:138****1234| 函数名 | 说明 | 语法 |
|---|---|---|
UPPER() | 转换为大写 | UPPER(str) |
LOWER() | 转换为小写 | LOWER(str) |
TRIM() | 移除首尾空格/指定字符 | TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str) |
LTRIM() | 移除左侧空格 | LTRIM(str) |
RTRIM() | 移除右侧空格 | RTRIM(str) |
示例 5:
SELECT UPPER('mysql') AS result; -- MYSQLSELECT LOWER('MYSQL') AS result; -- mysqlSELECT TRIM(' hello ') AS result; -- helloSELECT TRIM(LEADING '0' FROM '00123') AS result; -- 123SELECT TRIM(TRAILING 'x' FROM 'abcxxx') AS result; -- abc| 函数名 | 说明 | 语法 |
|---|---|---|
LPAD() | 左侧填充 | LPAD(str, len, padstr) |
RPAD() | 右侧填充 | RPAD(str, len, padstr) |
REPEAT() | 重复字符串 | REPEAT(str, count) |
示例 6:
-- 左侧补零(常用于生成工号)SELECT LPAD('123', 8, '0') AS emp_id;-- 结果:00000123-- 右侧填充SELECT RPAD('MySQL', 10, '*') AS result;-- 结果:MySQL*****-- 重复SELECT REPEAT('Go', 3) AS result;-- 结果:GoGoGo| 函数名 | 说明 | 语法 |
|---|---|---|
LOCATE() | 返回子字符串首次出现的位置 | LOCATE(substr, str [, pos]) |
POSITION() | 同 LOCATE(标准 SQL) | POSITION(substr IN str) |
INSTR() | 返回子字符串首次出现的位置 | INSTR(str, substr) |
REPLACE() | 替换子字符串 | REPLACE(str, from_str, to_str) |
INSERT() | 在指定位置插入/替换 | INSERT(str, pos, len, newstr) |
注意:
LOCATE()不区分大小写,与INSTR()功能相同但参数顺序相反。
示例 7:
-- 查找位置(不区分大小写)SELECT LOCATE('world', 'Hello World') AS position; -- 7SELECT INSTR('Hello World', 'world') AS position; -- 7-- SQL 标准写法SELECT POSITION('world' IN 'Hello World') AS position; -- 7-- 替换SELECT REPLACE('Hello World', 'World', 'MySQL') AS result;-- Hello MySQL-- 指定位置替换SELECT INSERT('Hello World', 7, 5, 'CSDN') AS result;-- Hello CSDN| 函数名 | 说明 | 语法 |
|---|---|---|
LENGTH() | 返回字节长度 | LENGTH(str) |
CHAR_LENGTH() / CHARACTER_LENGTH() | 返回字符长度 | CHAR_LENGTH(str) |
BIT_LENGTH() | 返回比特长度 | BIT_LENGTH(str) |
CHARSET() | 返回字符集 | CHARSET(str) |
重要区别:
LENGTH()返回字节长度,中文 UTF-8 编码下每个字符占 3 字节;CHAR_LENGTH()返回字符个数。
示例 8:
SELECT CHAR_LENGTH('Hello') AS char_len, -- 5(字符数) LENGTH('Hello') AS byte_len, -- 5(字节数) CHAR_LENGTH('你好') AS cn_char_len,-- 2(字符数) LENGTH('你好') AS cn_byte_len; -- 6(UTF-8 每中文字符 3 字节)| 函数名 | 说明 | 示例 |
|---|---|---|
ASCII(str) | 返回最左侧字符的 ASCII 值 | SELECT ASCII('A'); → 65 |
CHAR(n, ...) | 返回各整数对应的字符 | SELECT CHAR(65, 66, 67); → ABC |
REVERSE(str) | 反转字符串 | SELECT REVERSE('abc'); → cba |
SPACE(n) | 返回 n 个空格 | SELECT SPACE(5); |
STRCMP(s1, s2) | 字符串比较(相等为 0) | SELECT STRCMP('abc', 'abd'); → -1 |
FORMAT(n, d) | 格式化数字(千分位) | SELECT FORMAT(1234567.89, 2); → 1,234,567.89 |
ELT(n, s1, s2, ...) | 返回第 n 个字符串 | SELECT ELT(2, 'a', 'b', 'c'); → b |
FIELD(s, s1, s2, ...) | 返回 s 在列表中的位置 | SELECT FIELD('b', 'a', 'b', 'c'); → 2 |
FIND_IN_SET(s, list) | 返回 s 在逗号列表中的位置 | SELECT FIND_IN_SET('b', 'a,b,c'); → 2 |
| 函数名 | 说明 |
|---|---|
NOW() | 当前日期时间 |
CURDATE() / CURRENT_DATE() | 当前日期 |
CURTIME() / CURRENT_TIME() | 当前时间 |
SYSDATE() | 当前日期时间(执行时取值,NOW() 是语句开始时取值) |
UTC_DATE() / UTC_TIME() / UTC_TIMESTAMP() | UTC 时间 |
示例 9:
SELECT NOW(); -- 2024-01-15 10:30:45SELECT CURDATE(); -- 2024-01-15SELECT CURTIME(); -- 10:30:45SELECT UTC_TIMESTAMP();-- 2024-01-15 02:30:45(UTC 时间)
| 函数名 | 说明 | 示例 |
|---|---|---|
YEAR(date) | 提取年份 | SELECT YEAR('2024-06-15'); → 2024 |
MONTH(date) | 提取月份 | SELECT MONTH('2024-06-15'); → 6 |
DAY(date) / DAYOFMONTH(date) | 提取日 | SELECT DAY('2024-06-15'); → 15 |
HOUR(time) | 提取小时 | SELECT HOUR('10:30:45'); → 10 |
MINUTE(time) | 提取分钟 | SELECT MINUTE('10:30:45'); → 30 |
SECOND(time) | 提取秒 | SELECT SECOND('10:30:45'); → 45 |
DAYNAME(date) | 星期名称 | SELECT DAYNAME('2024-06-15'); → Saturday |
DAYOFWEEK(date) | 星期索引(周日=1) | SELECT DAYOFWEEK('2024-06-15'); → 7 |
DAYOFYEAR(date) | 一年中的第几天 | SELECT DAYOFYEAR('2024-06-15'); → 167 |
WEEK(date [, mode]) | 一年中的第几周 | SELECT WEEK('2024-06-15'); |
QUARTER(date) | 季度 | SELECT QUARTER('2024-06-15'); → 2 |
LAST_DAY(date) | 月份最后一天 | SELECT LAST_DAY('2024-06-15'); → 2024-06-30 |
| 函数名 | 说明 | 语法 |
|---|---|---|
DATE_ADD(date, INTERVAL expr unit) | 日期加 | DATE_ADD(date, INTERVAL 3 DAY) |
DATE_SUB(date, INTERVAL expr unit) | 日期减 | DATE_SUB(date, INTERVAL 1 MONTH) |
ADDDATE(date, INTERVAL expr unit) | 同 DATE_ADD | ADDDATE(date, INTERVAL expr unit) |
SUBDATE(date, INTERVAL expr unit) | 同 DATE_SUB | SUBDATE(date, INTERVAL expr unit) |
DATEDIFF(date1, date2) | 日期差(天数) | DATEDIFF(date1, date2) |
TIMESTAMPDIFF(unit, dt1, dt2) | 时间差(指定单位) | TIMESTAMPDIFF(DAY, dt1, dt2) |
ADDTIME(expr1, expr2) | 时间相加 | ADDTIME('10:30:00', '01:30:00') |
INTERVAL 常用单位:MICROSECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR。
示例 10:
-- 加 3 天SELECT DATE_ADD('2024-01-15', INTERVAL 3 DAY) AS result;-- 2024-01-18-- 减 1 个月SELECT DATE_SUB('2024-01-15', INTERVAL 1 MONTH) AS result;-- 2023-12-15-- 日期差SELECT DATEDIFF('2024-03-01', '2024-02-15') AS days_diff;-- 15-- 时间差SELECT TIMESTAMPDIFF(HOUR, '2024-01-15 08:00:00', '2024-01-15 17:30:00') AS hours;-- 9-- 计算年龄SELECT TIMESTAMPDIFF(YEAR, '1990-05-20', CURDATE()) AS age;| 函数名 | 说明 | 语法 |
|---|---|---|
DATE_FORMAT(date, format) | 日期格式化 | DATE_FORMAT(date, format) |
TIME_FORMAT(time, format) | 时间格式化 | TIME_FORMAT(time, format) |
STR_TO_DATE(str, format) | 字符串转日期 | STR_TO_DATE(str, format) |
常用格式化符号:
| 格式符 | 说明 | 示例输出 |
|---|---|---|
%Y | 四位年份 | 2024 |
%y | 两位年份 | 24 |
%m | 月份(01-12) | 01 |
%c | 月份(1-12) | 1 |
%d | 日期(01-31) | 15 |
%H | 小时(00-23) | 10 |
%i | 分钟(00-59) | 30 |
%s | 秒(00-59) | 45 |
%W | 星期名称 | Monday |
%a | 星期缩写 | Mon |
%M | 月份名称 | January |
示例 11:
-- 格式化SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日 %H:%i:%s') AS formatted;-- 2024年01月15日 10:30:45-- 字符串转日期SELECT STR_TO_DATE('2024-01-15', '%Y-%m-%d') AS date_val;-- 2024-01-15-- 时间格式化SELECT TIME_FORMAT('10:30:45', '%H时%i分%s秒') AS time_str;-- 10时30分45秒| 函数名 | 说明 |
|---|---|
CONVERT_TZ(dt, from_tz, to_tz) | 时区转换 |
TO_DAYS(date) | 日期转天数(公元 0 年起) |
FROM_DAYS(n) | 天数转日期 |
TO_SECONDS(expr) | 时间转秒 |
UNIX_TIMESTAMP([date]) | 返回 Unix 时间戳 |
FROM_UNIXTIME(unix_timestamp [, format]) | Unix 时间戳转日期 |
EXTRACT(unit FROM date) | 提取日期部分 |
MAKEDATE(year, dayofyear) | 根据年份和天数创建日期 |
MAKETIME(h, m, s) | 根据时分秒创建时间 |
GET_FORMAT(type, style) | 返回格式字符串 |
窗口函数是 MySQL 8.0 引入的重要特性,作用类似于分组聚合,但不会将分组结果聚合成一条记录,而是将结果保留在每一条数据中。
| 函数名 | 说明 |
|---|---|
ROW_NUMBER() | 为每行分配唯一的行号(对等行也不同) |
RANK() | 排名,对等行排名相同,有间隔 |
DENSE_RANK() | 排名,对等行排名相同,无间隔 |
示例 12:
-- 假设有 scores 表:student, subject, scoreSELECT student, subject, score, ROW_NUMBER() OVER (ORDER BY score DESC) AS row_num, RANK() OVER (ORDER BY score DESC) AS rank_val, DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank_valFROM scores;-- 结果对比(分数相同时):-- student | score | row_num | rank_val | dense_rank_val-- Alice | 95 | 1 | 1 | 1-- Bob | 95 | 2 | 1 | 1-- Charlie | 90 | 3 | 3 | 2
从 MySQL 8.0.2 开始,窗口函数不再需要显式的
FROM DUAL,可直接在普通查询中使用。
| 函数名 | 说明 |
|---|---|
LEAD(expr [, offset] [, default]) | 向后偏移(当前行之后的行) |
LAG(expr [, offset] [, default]) | 向前偏移(当前行之前的行) |
FIRST_VALUE(expr) | 窗口帧中第一行的值 |
LAST_VALUE(expr) | 窗口帧中最后一行的值 |
NTH_VALUE(expr, n) | 窗口帧中第 n 行的值 |
示例 13:
-- LAG/LEAD 计算环比SELECT order_date, daily_amount, LAG(daily_amount, 1) OVER (ORDER BY order_date) AS prev_day_amount, daily_amount - LAG(daily_amount, 1) OVER (ORDER BY order_date) AS diffFROM daily_sales;
| 函数名 | 说明 |
|---|---|
CUME_DIST() | 累计分布值(≤当前行值的行数 / 总行数) |
PERCENT_RANK() | 百分比排名 |
NTILE(n) | 将分区划分为 n 个分组 |
示例 14:
SELECT student, score, NTILE(4) OVER (ORDER BY score DESC) AS quartile, PERCENT_RANK() OVER (ORDER BY score DESC) AS pct_rankFROM scores;
function_name([expr]) OVER ( [PARTITION BY expr, ...] -- 分区 [ORDER BY expr [ASC|DESC]] -- 排序 [frame_clause] -- 窗口帧范围)
常见 frame_clause:
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -- 默认ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING -- 前后各一行ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING -- 当前行到末尾RANGE BETWEEN INTERVAL 1 DAY PRECEDING AND CURRENT ROW -- 时间范围
| 函数名 | 说明 | 示例 |
|---|---|---|
ABS(x) | 绝对值 | SELECT ABS(-5); → 5 |
MOD(n, m) | 取余 | SELECT MOD(10, 3); → 1 |
SQRT(x) | 平方根 | SELECT SQRT(16); → 4 |
POW(x, y) / POWER(x, y) | x 的 y 次方 | SELECT POW(2, 3); → 8 |
SIGN(x) | 符号(正=1,负=-1,0=0) | SELECT SIGN(-5); → -1 |
| 函数名 | 说明 | 示例 |
|---|---|---|
CEIL(x) / CEILING(x) | 向上取整 | SELECT CEIL(3.14); → 4 |
FLOOR(x) | 向下取整 | SELECT FLOOR(3.99); → 3 |
ROUND(x [, d]) | 四舍五入 | SELECT ROUND(3.14159, 2); → 3.14 |
TRUNCATE(x, d) | 截断(去尾法) | SELECT TRUNCATE(3.999, 1); → 3.9 |
ROUND 的 d 为负数时:
SELECT ROUND(88.234, -1); -- 90SELECT ROUND(88.234, -2); -- 100
| 函数名 | 说明 | 示例 |
|---|---|---|
RAND([seed]) | 生成 [0, 1) 随机数 | SELECT RAND(); |
SIN(x) / COS(x) / TAN(x) | 三角函数 | SELECT SIN(PI()/2); → 1 |
ASIN(x) / ACOS(x) / ATAN(x) | 反三角函数 | SELECT ASIN(0); → 0 |
PI() | 圆周率 π | SELECT PI(); → 3.141593 |
生成指定范围随机数:
-- [a, b) 之间的随机数:RAND() * (b - a) + a-- 生成 [5, 10) 的随机数SELECT RAND() * 5 + 5;-- 生成 [1, 100] 的随机整数SELECT FLOOR(RAND() * 100) + 1;
| 函数名 | 说明 |
|---|---|
EXP(x) | e 的 x 次方 |
LN(x) / LOG(x) | 自然对数 |
LOG2(x) | 以 2 为底 |
LOG10(x) | 以 10 为底 |
LOG(b, x) | 以 b 为底 |
RADIANS(x) | 角度转弧度 |
DEGREES(x) | 弧度转角度 |
| 函数名 | 说明 | 语法 |
|---|---|---|
IF(expr, v1, v2) | 条件判断 | IF(score >= 60, '及格', '不及格') |
IFNULL(v1, v2) | NULL 值替换 | IFNULL(nickname, '匿名用户') |
NULLIF(v1, v2) | v1=v2 返回 NULL,否则返回 v1 | NULLIF(expr, 0) |
COALESCE(v1, v2, ...) | 返回第一个非 NULL 值 | COALESCE(mobile, phone, '无') |
CASE WHEN ... THEN ... ELSE ... END | 多条件判断 | 见下方示例 |
示例 15:
-- IF 简单判断SELECT name, IF(score >= 60, '通过', '未通过') AS result FROM exams;-- IFNULL 处理 NULLSELECT IFNULL(avatar_url, '/images/default.png') AS avatar FROM users;-- NULLIF 避免除零错误SELECT amount / NULLIF(quantity, 0) AS unit_price FROM orders;-- COALESCE 优先取值SELECT COALESCE(mobile, phone, email, '无联系方式') AS contact FROM users;-- CASE 多条件判断SELECT name, score, CASE WHEN score >= 90 THEN '优秀' WHEN score >= 80 THEN '良好' WHEN score >= 60 THEN '及格' ELSE '不及格' END AS gradeFROM students;
MySQL 8.0 提供了强大的 JSON 处理能力。
| 函数名 | 说明 | 示例 |
|---|---|---|
JSON_ARRAY(val, ...) | 创建 JSON 数组 | SELECT JSON_ARRAY(1, 2, 'hello'); → [1, 2, "hello"] |
JSON_OBJECT(key, val, ...) | 创建 JSON 对象 | SELECT JSON_OBJECT('id', 1, 'name', 'Alice'); → {"id":1, "name":"Alice"} |
JSON_QUOTE(str) | 将字符串转为 JSON 值 | SELECT JSON_QUOTE('hello'); → "hello" |
| 函数名 | 说明 | 语法 |
|---|---|---|
JSON_EXTRACT(doc, path) | 提取值 | JSON_EXTRACT(doc, '$.key') |
-> | JSON_EXTRACT 简写 | doc->'$.key' |
->> | 提取并取消引用(返回文本) | doc->>'$.key' |
示例 16:
-- 假设 data 列存储:{"name":"Alice","address":{"city":"Beijing"}}-- 提取字段SELECT data->'$.name' AS name FROM users; -- "Alice"(带引号)SELECT data->>'$.name' AS name FROM users; -- Alice(文本)-- 嵌套取值SELECT data->>'$.address.city' AS city FROM users; -- Beijing-- 提取数组元素SELECT JSON_EXTRACT('[1, 2, 3]', '$[0]'); -- 1| 函数名 | 说明 |
|---|---|
JSON_SET(doc, path, val [, ...]) | 设置值(存在则替换,不存在则插入) |
JSON_INSERT(doc, path, val [, ...]) | 插入值(不存在才插入) |
JSON_REPLACE(doc, path, val [, ...]) | 替换值(存在才替换) |
JSON_REMOVE(doc, path [, ...]) | 删除值 |
JSON_MERGE_PRESERVE(doc, doc) | 合并 JSON |
JSON_MERGE_PATCH(doc, doc) | 合并 JSON(RFC 7396) |
| 函数名 | 说明 |
|---|---|
JSON_TYPE(val) | 返回 JSON 值类型 |
JSON_VALID(val) | 检查是否为有效 JSON |
JSON_LENGTH(val [, path]) | 返回长度 |
JSON_DEPTH(val) | 返回最大深度 |
JSON_KEYS(val [, path]) | 返回所有键 |
JSON_CONTAINS(target, candidate [, path]) | 判断是否包含 |
JSON_PRETTY(val) | 格式化输出 |
JSON_TABLE(expr, path COLUMNS ...) | JSON 转结果集 |
示例 17 — JSON_TABLE:
-- 将 JSON 数组转为表格数据SELECT * FROM JSON_TABLE( '[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]', '$[*]' COLUMNS ( id INT PATH '$.id', name VARCHAR(50) PATH '$.name' )) AS jt;-- 结果:-- +------+-------+-- | id | name |-- +------+-------+-- | 1 | Alice |-- | 2 | Bob |-- +------+-------+| 函数名 | 说明 | 语法 |
|---|---|---|
MD5(str) | 计算 MD5 校验和 | SELECT MD5('hello'); |
SHA(str) / SHA1(str) | 计算 SHA-1 | SELECT SHA('hello'); |
SHA2(str, hash_length) | 计算 SHA-2 (224/256/384/512) | SELECT SHA2('hello', 256); |
CRC32(str) | 计算 CRC32 校验和 | SELECT CRC32('hello'); |
| 函数名 | 说明 |
|---|---|
AES_ENCRYPT(str, key) | AES 加密 |
AES_DECRYPT(crypt_str, key) | AES 解密 |
COMPRESS(str) | 压缩 |
UNCOMPRESS(str) | 解压 |
RANDOM_BYTES(n) | 生成随机字节 |
UUID() | 生成 UUID |
UUID_SHORT() | 生成短 UUID(64 位无符号整数) |
注意:MySQL 8.0 已弃用
PASSWORD()、ENCRYPT()、DES_ENCRYPT()、DES_DECRYPT()等函数。
信息函数用于获取 MySQL 系统和会话相关信息。
| 函数名 | 说明 | 示例 |
|---|---|---|
DATABASE() / SCHEMA() | 当前数据库名 | SELECT DATABASE(); |
VERSION() | MySQL 版本 | SELECT VERSION(); → 8.0.32 |
USER() / CURRENT_USER() | 当前用户 | SELECT USER(); |
CONNECTION_ID() | 连接 ID | SELECT CONNECTION_ID(); |
LAST_INSERT_ID() | 最后插入的自增 ID | SELECT LAST_INSERT_ID(); |
ROW_COUNT() | 上条语句影响的行数 | INSERT INTO ...; SELECT ROW_COUNT(); |
FOUND_ROWS() | 最后 SELECT 的结果行数(不加 LIMIT 时的总行数) | SELECT FOUND_ROWS(); |
BENCHMARK(n, expr) | 性能测试 | SELECT BENCHMARK(1000000, MD5('test')); |
CHARSET(str) | 返回字符集 | SELECT CHARSET('hello'); → utf8mb4 |
COLLATION(str) | 返回排序规则 | SELECT COLLATION('hello'); |
| 函数/操作符 | 说明 | 示例 |
|---|---|---|
CAST(expr AS type) | 类型转换 | SELECT CAST('123' AS SIGNED); |
CONVERT(expr, type) | 类型转换 | SELECT CONVERT('2024-01-15', DATE); |
BINARY expr | 转为二进制字符串(大小写敏感比较时常用) | SELECT 'ABC' = 'abc' → 1(不区分大小写) |
支持的转换类型:BINARY, CHAR, DATE, DATETIME, TIME, DECIMAL, SIGNED, UNSIGNED, DOUBLE, FLOAT, JSON。
示例 18:
-- 字符串转整数SELECT CAST('123' AS SIGNED) + 1; -- 124-- 整数转字符串SELECT CONCAT('编号:', CAST(123 AS CHAR)); -- 编号:123-- 字符串转日期SELECT CAST('2024-01-15' AS DATE); -- 2024-01-15-- 转为 JSONSELECT CAST('{"id":1}' AS JSON);-- 大小写敏感比较SELECT 'ABC' = 'abc'; -- 1(不区分大小写)SELECT BINARY 'ABC' = 'abc'; -- 0(区分大小写)| 函数名 | 说明 | 示例 |
|---|---|---|
GREATEST(v1, v2, ...) | 返回最大值 | SELECT GREATEST(3, 7, 2); → 7 |
LEAST(v1, v2, ...) | 返回最小值 | SELECT LEAST(3, 7, 2); → 2 |
ISNULL(expr) | 判断 NULL | SELECT ISNULL(NULL); → 1 |
COALESCE(v1, ...) | 返回第一个非 NULL 值 | 见第 6 节 |
ANY_VALUE(expr) | 抑制 ONLY_FULL_GROUP_BY 校验 | SELECT dept, ANY_VALUE(name) FROM emp GROUP BY dept; |
| 函数名 | 说明 | 示例 |
|---|---|---|
BIN(n) | 十进制转二进制 | SELECT BIN(10); → 1010 |
OCT(n) | 十进制转八进制 | SELECT OCT(10); → 12 |
HEX(n) | 十进制转十六进制 | SELECT HEX(10); → A |
CONV(n, from_base, to_base) | 任意进制转换 | SELECT CONV('FF', 16, 10); → 255 |
| 函数名 | 说明 |
|---|---|
GET_LOCK(name, timeout) | 获取命名锁 |
RELEASE_LOCK(name) | 释放命名锁 |
IS_FREE_LOCK(name) | 检查锁是否空闲 |
IS_USED_LOCK(name) | 返回锁的连接 ID |
在 MySQL 8.0 的 InnoDB 引擎中,COUNT(*) 和 COUNT(1) 在性能上几乎没有区别,优化器会将它们做同样的优化处理。不同点在于:
COUNT(字段) 会忽略 NULL 值
COUNT(*) 和 COUNT(1) 统计所有行,包括 NULL 行
LENGTH(str):返回字节长度,UTF-8 中文字符占 3 字节
CHAR_LENGTH(str):返回字符个数,每个字符算 1 个
NOW() 在语句执行开始时取值,同一事务中多次调用返回相同值;SYSDATE() 在每次调用时实时取值,多次调用可能返回不同时间。
当存在相同值时,RANK() 会跳过排名(1, 1, 3),DENSE_RANK() 不会跳过(1, 1, 2)。
MySQL 8.0 中已弃用或移除的函数包括:PASSWORD()、ENCRYPT()、DES_ENCRYPT()、DES_DECRYPT()、OLD_PASSWORD() 等,请使用 MD5()、SHA2()、AES_ENCRYPT() 等替代。
使用 NULLIF 函数:
-- 如果 quantity 为 0,NULLIF 返回 NULL,除 NULL 结果为 NULLSELECT amount / NULLIF(quantity, 0) AS unit_price FROM orders;
本文系统梳理了 MySQL 8.0 的常用内置函数,涵盖以下十大类别:
| 类别 | 核心函数数量 | 典型应用场景 |
|---|---|---|
| 聚合函数 | ~15 | 数据统计、汇总分析 |
| 字符串函数 | ~60 | 文本处理、格式化 |
| 日期时间函数 | ~40 | 日期计算、格式化 |
| 窗口函数 | ~12 | 排名、环比分析、累计计算 |
| 数学函数 | ~30 | 数值运算、随机数 |
| 流程控制函数 | ~5 | 条件判断、NULL 处理 |
| JSON 函数 | ~30 | JSON 数据操作 |
| 加密压缩函数 | ~15 | 数据加密、校验 |
| 信息函数 | ~10 | 获取系统和会话信息 |
| 类型转换函数 | ~3 | 数据类型转换 |
建议将本文收藏,在实际开发中查阅参考。完整函数列表可查阅 MySQL 8.0 官方参考手册。
温馨提示:熟练掌握常用函数可以让你在写 SQL 时得心应手,但也要注意函数对性能的影响。在 WHERE 子句中对列使用函数(如
WHERE YEAR(created_at) = 2024)可能导致索引失效,建议在条件中直接使用范围比较(如WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01')。
樱花动漫APP下载-樱花动漫官方正版APP最新下载入口
premiere画中画大小位置调节方法 - premiere如何调节画中画大小和位置
丁香修剪技巧有哪些-如何用丁香修剪技巧打造优美树形
在Win2008 R2中如何删除DHCP管理工具-Win2008 R2怎样删除DHCP管理工具
如何通过支付宝阿宝自动匹配生活服务入口-怎样借助支付宝阿宝自动匹配生活服务入口
edius素材添加单门推效果的操作方法-edius素材如何添加单门推效果