文章目录
前言
环境:
- Window11
- MySQL-8.0.35
1.字符串函数
最常用的一种函数。
注意:在 MySQL 中,字符串的下标(或称为索引)是从 1 开始的,而不是从 0 开始。
函数 | 功能 |
---|---|
CONCAT(s1, s2, ..., sn) | 连接s1, s2, ..., sn 为一个字符串 |
INSERT(str, x, y, instr) | 将字符串str从第x位置开始,y个字符长的子串替换为字符串instr |
LOWER(str) | 将字符串str中的所有字符转换为小写 |
UPPER(str) | 将字符串str中的所有字符转换为大写 |
LEFT(str, x) | 返回字符串str最左边的x个字符 |
RIGHT(str, x) | 返回字符串str最右边的x个字符 |
LPAD(str, n, pad) | 用字符串pad对str最左边进行填充,直到长度为n个字符长度 |
RPAD(str, n, pad) | 用字符串pad对str最右边进行填充,直到长度为n个字符长度 |
LTRIM(str) | 去掉字符串str左侧的空格 |
RTRIM(str) | 去掉字符串str右侧的空格 |
REPEAT(str, x) | 返回str重复x次的结果 |
REPLACE(str, a, b) | 用字符串b替换字符串str中所有出现的字符串a |
STRCMP(s1, s2) | 比较字符串s1和s2 |
TRIM(str) | 去掉字符串行尾和行头的空格 |
SUBSTRING(str, x, y) | 返回从字符串str的x位置起y个字符长度的字符串 |
- CONCAT(s1, s2, ..., sn)函数,把传入的字符串连接成为一个字符串。但是如果其中有NULL,结果就是NULL,因为任何字符串和NULL进行连接的结果都是NULL。
sql
mysql> select concat('aa','bb','cc'), concat('aa','bb', null);
+------------------------+-------------------------+
| concat('aa','bb','cc') | concat('aa','bb', null) |
+------------------------+-------------------------+
| aabbcc | NULL |
+------------------------+-------------------------+
1 row in set (0.01 sec)
- INSERT(str, x, y, instr)函数,将字符串str从第x位置开始,y个字符长的字串替换为字符串instr。
sql
// 第6个位置也就是 H 开始,5个字符的长度 Hello 替换为 MySQL
mysql> select insert('12345Hello', 6, 5, 'MySQL');
+-------------------------------------+
| insert('12345Hello', 6, 5, 'MySQL') |
+-------------------------------------+
| 12345MySQL |
+-------------------------------------+
1 row in set (0.01 sec)
- LOWER(str) 和 UPPER(str)函数,把字符串转换为小写或者大写。
sql
mysql> select lower('我是大写转小写ABC'), upper('我是小写转大写abc');
+----------------------------+----------------------------+
| lower('我是大写转小写ABC') | upper('我是小写转大写abc') |
+----------------------------+----------------------------+
| 我是大写转小写abc | 我是小写转大写ABC |
+----------------------------+----------------------------+
1 row in set (0.00 sec)
- LEFT(str, x) 和 RIGTH(str, x)函数,分别是返回字符串最左边的x字符和最右边的x个字符,如果第二个参数为NULL,那么将不返回任何字符串,返回NULL。
sql
mysql> select left('abcdef', 5), right('abcdef', 5), left('abcdef', null);
+-------------------+--------------------+----------------------+
| left('abcdef', 5) | right('abcdef', 5) | left('abcdef', null) |
+-------------------+--------------------+----------------------+
| abcde | bcdef | NULL |
+-------------------+--------------------+----------------------+
1 row in set (0.01 sec)
- LPAD(str, n, pad) 和 RPAD(str, n, pad)函数,分别用字符串pad 对 str 最左边和最右边进行填充,直到长度为n个字符长度。
sql
mysql> select lpad('abc', 5, 00), lpad('abc', 5, 'hellomysql'), rpad('abc', 5, 0), rpad('abc', 5, 'hellomysql');
+--------------------+------------------------------+-------------------+------------------------------+
| lpad('abc', 5, 00) | lpad('abc', 5, 'hellomysql') | rpad('abc', 5, 0) | rpad('abc', 5, 'hellomysql') |
+--------------------+------------------------------+-------------------+------------------------------+
| 00abc | heabc | abc00 | abche |
+--------------------+------------------------------+-------------------+------------------------------+
1 row in set (0.01 sec)
- LTRIM(str) 和 RTRIM(str)函数,分别去掉字符串str左侧和右侧的空格。
sql
mysql> select ltrim(' |abc| '), rtrim(' |abc| ');
+----------------------+----------------------+
| ltrim(' |abc| ') | rtrim(' |abc| ') |
+----------------------+----------------------+
| |abc| | |abc| |
+----------------------+----------------------+
1 row in set (0.00 sec)
- REPEAT(str, x)函数,返回str重复x次的结果。
sql
mysql> select repeat('HelloMySQL==', 5);
+--------------------------------------------------------------+
| repeat('HelloMySQL==', 5) |
+--------------------------------------------------------------+
| HelloMySQL==HelloMySQL==HelloMySQL==HelloMySQL==HelloMySQL== |
+--------------------------------------------------------------+
1 row in set (0.00 sec)
- REPLACE(str, a, b)函数,用字符串b替换字符串str中所有出现的字符串a。
sql
mysql> select replace('abbaaccaaadd', 'a', '==');
+------------------------------------+
| replace('abbaaccaaadd', 'a', '==') |
+------------------------------------+
| ==bb====cc======dd |
+------------------------------------+
1 row in set (0.00 sec)
- STRCMP(s1, s2)函数,比较字符串s1和s2的ASCII码值的大小,如果s1<s2,返回-1。如果s1=s2,返回0。如果s1>s2,返回1.
sql
mysql> select strcmp('a','b'), strcmp('a','a'),strcmp('b','a');
+-----------------+-----------------+-----------------+
| strcmp('a','b') | strcmp('a','a') | strcmp('b','a') |
+-----------------+-----------------+-----------------+
| -1 | 0 | 1 |
+-----------------+-----------------+-----------------+
1 row in set (0.01 sec)
- SUBSTRING(str, x, y)函数,返回从字符串str中的第x位置起y个字符长度的字符串。
sql
mysql> select substring('abcdefg', '2', 5), substring('你好我是张三', 3, 4);
+------------------------------+---------------------------------+
| substring('abcdefg', '2', 5) | substring('你好我是张三', 3, 4) |
+------------------------------+---------------------------------+
| bcdef | 我是张三 |
+------------------------------+---------------------------------+
1 row in set (0.00 sec)
2.数值函数
处理数值方面的运算。
函数 | 功能 |
---|---|
ABS(x) | 返回x的绝对值 |
CEIL(x) | 返回大于x的最小整数值 |
FLOOR(x) | 返回小于x的最大整数值 |
MOD(x, y) | 返回x/y的模, 等价于前面运算符章节中的% |
RAND() | 返回0~1内的随机值 |
ROUND(x, y) | 返回参数x的四舍五入的有y位小数的值 |
TRUNCATE(x, y) | 返回数字x截断为y位小数的结果 |
- ABS(x)函数,返回x的绝对值。
sql
mysql> select abs(0.8), abs(-0.8);
+----------+-----------+
| abs(0.8) | abs(-0.8) |
+----------+-----------+
| 0.8 | 0.8 |
+----------+-----------+
1 row in set (0.00 sec)
- CEIL(x)函数,返回大于x的最小整数值。
sql
mysql> select ceil(-0.8), ceil(-1.5), ceil(0.8), ceil(1.5);
+------------+------------+-----------+-----------+
| ceil(-0.8) | ceil(-1.5) | ceil(0.8) | ceil(1.5) |
+------------+------------+-----------+-----------+
| 0 | -1 | 1 | 2 |
+------------+------------+-----------+-----------+
1 row in set (0.01 sec)
- FLOOR(x)函数,返回小于x的最大整数值。和上面的CEIL正好相反。
sql
mysql> select floor(-0.8), floor(-1.5), floor(0.8), floor(1.5);
+-------------+-------------+------------+------------+
| floor(-0.8) | floor(-1.5) | floor(0.8) | floor(1.5) |
+-------------+-------------+------------+------------+
| -1 | -2 | 0 | 1 |
+-------------+-------------+------------+------------+
1 row in set (0.00 sec)
- MOD(x, y)函数,返回 x/y 的模,等价于前面符号章节的%操作。x和y的值任何一个为NULL,结果就是NULL。
sql
mysql> select 10%3, 10%null, 10 mod 3, mod(10,3), mod(null, 3);
+------+---------+----------+-----------+--------------+
| 10%3 | 10%null | 10 mod 3 | mod(10,3) | mod(null, 3) |
+------+---------+----------+-----------+--------------+
| 1 | NULL | 1 | 1 | NULL |
+------+---------+----------+-----------+--------------+
1 row in set (0.00 sec)
- RAND()函数,返回0~1的随机值。
sql
mysql> select rand(), rand(), rand();
+--------------------+--------------------+--------------------+
| rand() | rand() | rand() |
+--------------------+--------------------+--------------------+
| 0.5018647653068088 | 0.8444691345509786 | 0.7167514075681115 |
+--------------------+--------------------+--------------------+
1 row in set (0.00 sec)
RAND函数可以取任意指定范围内的随机数,例如需要0~100之间的任意随机整数,可以如下操作:
sql
mysql> select ceil(rand()*100), ceil(rand()*100), ceil(rand()*100);
+------------------+------------------+------------------+
| ceil(rand()*100) | ceil(rand()*100) | ceil(rand()*100) |
+------------------+------------------+------------------+
| 6 | 11 | 36 |
+------------------+------------------+------------------+
1 row in set (0.00 sec)
- ROUND(x, y)函数,返回参数x的四舍五入的有y位小数的值。如果是整数,将会保留y位数量的0。如果不写y,则默认y就是0,也就是将四舍五入后取整。
sql
mysql> select round(1.456, 2), round(1.456), round(1.456, 4), round(1), round(1.456, 0), round(1,3);
+-----------------+--------------+-----------------+----------+-----------------+------------+
| round(1.456, 2) | round(1.456) | round(1.456, 4) | round(1) | round(1.456, 0) | round(1,3) |
+-----------------+--------------+-----------------+----------+-----------------+------------+
| 1.46 | 1 | 1.456 | 1 | 1 | 1 |
+-----------------+--------------+-----------------+----------+-----------------+------------+
1 row in set (0.00 sec)
- TRUNCATE(x, y)函数,返回数字x截断为y位小数的结果。注意和上面ROUND的区别,这里是截断不进行四舍五入操作。
sql
mysql> select truncate(1.456, 2), truncate(1.456, 4), truncate(1, 2);
+--------------------+--------------------+----------------+
| truncate(1.456, 2) | truncate(1.456, 4) | truncate(1, 2) |
+--------------------+--------------------+----------------+
| 1.45 | 1.456 | 1 |
+--------------------+--------------------+----------------+
1 row in set (0.00 sec)
3.日期和时间函数
常用的日期函数如下:
函数 | 功能 |
---|---|
CURDATE() | 返回当前日期 |
CURTIME() | 返回当前时间 |
NOW() | 返回当前日期和时间 |
UNIX_TIMESTAMP(date) | 返回日期date的UNIX时间戳 |
FROM_UNIXTIME | 返回UNIX时间戳的日期值 |
WEEK(date) | 返回日期date为一年中的第几周 |
YEAR(date) | 返回日期date的年份 |
HOUR(time) | 返回时间time的小时值 |
MINUTE(time) | 返回时间time的分钟值 |
MONTH(date) | 返回日期date为一年中的第几个月 |
MONTHNAME(date) | 返回日期date的月份名 |
DATE_FORMAT(date, fmt) | 返回按照字符串fmt格式化日期date后的值 |
DATE_ADD(date, INTERVAL expr type) | 返回一个日期或时间值加上一个时间间隔的时间值 |
DATEDIFF(expr, expr2) | 返回起始时间expr和结束日期expr2之间的天数 |
- CURDATE()函数,返回当前日期,只包含 年、月、日。
- CURTIME()函数,返回当前时间,只包含 时、分、秒。
- NOW()函数,返回当前日期和时间,年、月、日、时、分、秒都包含。
sql
mysql> select curdate(), curtime(), now();
+------------+-----------+---------------------+
| curdate() | curtime() | now() |
+------------+-----------+---------------------+
| 2024-04-24 | 16:00:26 | 2024-04-24 16:00:26 |
+------------+-----------+---------------------+
1 row in set (0.01 sec)
- UNIX_TIMESTAMP(date)函数,返回日期date的UNIX时间戳。
sql
mysql> select unix_timestamp(now());
+-----------------------+
| unix_timestamp(now()) |
+-----------------------+
| 1713946688 |
+-----------------------+
1 row in set (0.01 sec)
- FROM_UNIXTIME(unixtime)函数,返回UNIXTIME时间戳的日期值,和上面的UNIX_TIMESTAMP(date)函数互为逆操作。
sql
mysql> select unix_timestamp(now()), now();
+-----------------------+---------------------+
| unix_timestamp(now()) | now() |
+-----------------------+---------------------+
| 1713946819 | 2024-04-24 16:20:19 |
+-----------------------+---------------------+
1 row in set (0.00 sec)
// 对比上面unix_timestamp的值,互为逆操作
mysql> select from_unixtime(1713946819);
+---------------------------+
| from_unixtime(1713946819) |
+---------------------------+
| 2024-04-24 16:20:19 |
+---------------------------+
1 row in set (0.00 sec)
- WEEK(date) 和 YEAR(date)函数,分别返回参数date是一年中的第几周 和 哪一年。
sql
mysql> select week(now()), year(now());
+-------------+-------------+
| week(now()) | year(now()) |
+-------------+-------------+
| 16 | 2024 |
+-------------+-------------+
1 row in set (0.00 sec)
- HOUR(time) 和 MINUTE(time)函数,分别返回参数time的小时 和 分钟。
sql
mysql> select now(), hour(now()), minute(now());
+---------------------+-------------+---------------+
| now() | hour(now()) | minute(now()) |
+---------------------+-------------+---------------+
| 2024-04-24 16:23:27 | 16 | 23 |
+---------------------+-------------+---------------+
1 row in set (0.01 sec)
- MONTHNAME(date)函数,返回参数date的英文月份名称。
- MONTH(date)函数,返回参数date为一年中的第几个月。
sql
mysql> select now(), monthname(now()), month(now());
+---------------------+------------------+--------------+
| now() | monthname(now()) | month(now()) |
+---------------------+------------------+--------------+
| 2024-04-24 16:25:18 | April | 4 |
+---------------------+------------------+--------------+
1 row in set (0.00 sec)
- DATE_FORMAT(date, fmt)函数,按照字符串fmt格式化日期date,fmt的格式符如下:
- %Y:四位数的年份
- %y:两位数的年份
- %m:两位数的月份(01-12)
- %c:月份(1-12)
- %d:两位数的日(01-31)
- %e:日(1-31)
- %H:两位数的小时(00-23)
- %h 或 %I:两位数的小时(01-12)
- %i:两位数的分钟(00-59)
- %s:两位数的秒(00-59)
- %p:AM 或 PM
- %r:时间,12 小时制(hh:mm:ss AM 或 PM)
- %T 或 %X:时间,24 小时制(hh:mm:ss)
- %k:小时(0-23)
- %l:小时(1-12)
- %W:星期几的完整名称(例如:Sunday)
- %a:星期几的缩写(例如:Sun)
- %j:一年的第几天(001-366)
- %U:周数(星期天为一周的开始,00-53)
- %u:周数(星期一为一周的开始,00-53)
- %V:周数(星期天为一周的开始,但第一周至少要有 4 天在这一年中,1-53)
- %v:周数(星期一为一周的开始,但第一周至少要有 4 天在这一年中,1-53)
- %D:美国格式的日期(月/日/年)
- %F:年-月-日格式的日期(YYYY-MM-DD)
sql
mysql> select date_format(now(), '%Y-%m-%d %H:%i:%s'),date_format(now(), '%Y/%m/%d %H-%i-%s');
+-----------------------------------------+-----------------------------------------+
| date_format(now(), '%Y-%m-%d %H:%i:%s') | date_format(now(), '%Y/%m/%d %H-%i-%s') |
+-----------------------------------------+-----------------------------------------+
| 2024-04-24 16:31:36 | 2024/04/24 16-31-36 |
+-----------------------------------------+-----------------------------------------+
1 row in set (0.00 sec)
- DATE_ADD(date, INTERVAL expr type)函数,用于向日期值添加指定的时间间隔,INTERVAL是间隔类型的关键字,expr是表达式,要添加的时间间隔的数量或值,type表示间隔类型,如下:
expr间隔类型 | 描述 | 格式 |
---|---|---|
HOUR | 小时 | hh |
MINUTE | 分 | mm |
SECOND | 秒 | ss |
YEAR | 年 | YY |
MONTH | 月 | MM |
DAY | 日 | DD |
YEAR_MONTH | 年和月 | YY-MM |
DAY_HOUR | 日和小时 | DD hh |
DAY_MINUTE | 日和分钟 | DD hh:mm |
DAY_SECOND | 日和秒 | DD hh:mm:ss |
HOUR_MINUTE | 小时和分 | hh:mm |
HOUR_SECOND | 小时和秒 | hh:ss |
MINUTE_SECOND | 分钟和秒 | mm:ss |
sql
// -1 day 可以用来表示减去日给定的日期
mysql> select now(), date_add(now(), interval 30 day), date_add(now(), interval 1 month), date_add(now(), interval -1 day);
+---------------------+----------------------------------+-----------------------------------+----------------------------------+
| now() | date_add(now(), interval 30 day) | date_add(now(), interval 1 month) | date_add(now(), interval -1 day) |
+---------------------+----------------------------------+-----------------------------------+----------------------------------+
| 2024-04-24 16:42:58 | 2024-05-24 16:42:58 | 2024-05-24 16:42:58 | 2024-04-23 16:42:58 |
+---------------------+----------------------------------+-----------------------------------+----------------------------------+
1 row in set (0.01 sec)
- DATEDIFF(date1, date2)函数,用来计算两个日期之间相差的天数。date1 - date2的,所以可能出现负数的差值,如下。
sql
mysql> select datediff('2024-04-20',now()), now(), datediff(now(), '2024-04-20');
+------------------------------+---------------------+-------------------------------+
| datediff('2024-04-20',now()) | now() | datediff(now(), '2024-04-20') |
+------------------------------+---------------------+-------------------------------+
| -4 | 2024-04-24 16:45:34 | 4 |
+------------------------------+---------------------+-------------------------------+
1 row in set (0.00 sec)
4.流程函数
这类函数可以在SQL中实现条件选择,如下:
函数 | 功能 |
---|---|
IF(value, t, f) | 如果value是真,返回t,否则返回f |
IFNULL(value1, value2) | 如果value1不为空,返回value1,否则返回value2 |
CASE WHEN [expr] THEN [result] ... ELSE [default] END | 如果expr表达式是真,返回result,否则返回default |
CASE [expr] WHEN [value] THEN [result] ... ELSE [default] END | 如果expr等于value1,返回result,否则返回default |
这里测试示例我们模拟人员表的年龄进行分类,先创建一个person表,并插入一些数据,如下:
sql
// 主键自增
mysql> create table person (
-> id int primary key auto_increment,
-> age int
-> );
Query OK, 0 rows affected (0.02 sec)
// 插入年龄数据
mysql> insert into person (age) values (10),(18),(20),(30),(50),(70),(90),(100),(null);
Query OK, 9 rows affected (0.01 sec)
Records: 9 Duplicates: 0 Warnings: 0
- IF(value, t, f)函数,这里认为年龄在60以上的属于高龄,用 "老人" 表示,而60以下的属于年轻人, 用"年轻人"表示。
sql
mysql> select id, age, if(age>60, '老人', '年轻人') as info from person;
+----+------+--------+
| id | age | info |
+----+------+--------+
| 1 | 10 | 年轻人 |
| 2 | 18 | 年轻人 |
| 3 | 20 | 年轻人 |
| 4 | 30 | 年轻人 |
| 5 | 50 | 年轻人 |
| 6 | 70 | 老人 |
| 7 | 90 | 老人 |
| 8 | 100 | 老人 |
| 9 | NULL | 年轻人 |
+----+------+--------+
9 rows in set (0.00 sec)
- IFNULL(value1, value2)函数,这个函数一般用来替换NULL值,NULL值是不能参与数值运算的,举例替换NULL值为0,如下
sql
// id = 9的那条数据,ifnull替换为了0
mysql> select id, age, ifnull(age, 0) from person;
+----+------+----------------+
| id | age | ifnull(age, 0) |
+----+------+----------------+
| 1 | 10 | 10 |
| 2 | 18 | 18 |
| 3 | 20 | 20 |
| 4 | 30 | 30 |
| 5 | 50 | 50 |
| 6 | 70 | 70 |
| 7 | 90 | 90 |
| 8 | 100 | 100 |
| 9 | NULL | 0 |
+----+------+----------------+
9 rows in set (0.00 sec)
- CASE WHEN [expr] THEN [result] ... ELSE [default] END 函数,允许根据一个或多个条件返回不同的值,它的基本完整语法如下:
sql
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE resultN
END
- condition1, condition2, ... 是要评估的条件。
- result1, result2, ... 是当对应条件为真时返回的结果。
- ELSE 子句是可选的,用于当所有条件都不满足时返回的结果。
- END 关键字标志着 CASE 语句的结束。
继续使用 年龄在60以上的属于高龄,用 "老人" 表示,而60以下的属于年轻人, 用"年轻人"表示 的这个列子,如下:
sql
// 注意 else 的使用,如果没有前面符合条件的,都是用 else 来表示
mysql> select id, age, case when age>60 then '老人' when age< 60 then '年轻人' else '=====' end from person;
+----+------+--------------------------------------------------------------------------+
| id | age | case when age>60 then '老人' when age< 60 then '年轻人' else '=====' end |
+----+------+--------------------------------------------------------------------------+
| 1 | 10 | 年轻人 |
| 2 | 18 | 年轻人 |
| 3 | 20 | 年轻人 |
| 4 | 30 | 年轻人 |
| 5 | 50 | 年轻人 |
| 6 | 70 | 老人 |
| 7 | 90 | 老人 |
| 8 | 100 | 老人 |
| 9 | NULL | ===== |
+----+------+--------------------------------------------------------------------------+
9 rows in set (0.00 sec)
- CASE [expr] WHEN [value] THEN [result] ... ELSE [default] END 函数,这其实是case的一个简单函数,case后面跟着列名或者列的表达式,when后面跟表达式(case后面的)所有可能的值(不是值得范围,是具体等于的值),如果相等,就返回then后面的值,如下:
sql
mysql> select id, age, (case age when 10 then '孩子' when '20' then '年轻人' when 100 then '老者' else '===' end) as info from person;
+----+------+--------+
| id | age | info |
+----+------+--------+
| 1 | 10 | 孩子 |
| 2 | 18 | === |
| 3 | 20 | 年轻人 |
| 4 | 30 | === |
| 5 | 50 | === |
| 6 | 70 | === |
| 7 | 90 | === |
| 8 | 100 | 老者 |
| 9 | NULL | === |
+----+------+--------+
9 rows in set (0.00 sec)
5.JSON函数
在前面深入浅出MySQL-02-【MySQL支持的数据类型】中说明过MySQL的JSON数据类型,对于JSON函数的操作,也就是各种查询、修改等,在这里说明。
函数类型 | 函数 | 功能 |
---|---|---|
创建JSON | JSON_ARRAY() | 创建JSON数组 |
创建JSON | JSON_OBJECT() | 创建JSON对象 |
创建JSON | JSON_QUOTE() JSON_UNQUOTE() | 加上/去掉JSON文档两边的双引号 |
查询JSON | JSON_CONTAINS() | 查询文档中是否包含指定的元素 |
查询JSON | JSON_CONTAINS_PATH() | 查询文档中是否包含指定的路径 |
查询JSON | JSON_EXTRACT() -> ->> | 根据条件提取文档中的数据 |
查询JSON | JSON_KEYS() | 提取所有key的集合 |
查询JSON | JSON_SEARCH() | 返回所有符合条件的路径集合 |
修改JSON | JSON_MERGE(废弃于版本5.7.22) JSON_MERGE_PRESERVE() | 将两个文档合并 |
修改JSON | JSON_ARRAY_APPEND() | 数组尾部追加元素 |
修改JSON | JSON_ARRAY_INSERT() | 在数组的指定位置插入元素 |
修改JSON | JSON_REMOVE() | 删除文档中指定位置的元素 |
修改JSON | JSON_REPLACE() | 替换文档中指定位置的元素 |
修改JSON | JSON_SET() | 给文档中指定位置的元素设置新值,如果元素不存在,就进行插入 |
查询JSON元数据 | JSON_DEPTH() | JSON文档的深度(元素的最大嵌套层数) |
查询JSON元数据 | JSON_LENGTH() | JSON文档的长度(元素个数) |
查询JSON元数据 | JSON_TYPE() | JSON文档类型(数组、对象、标量类型等) |
查询JSON元数据 | JSON_VAILD() | JSON格式是否合法 |
其他函数 | JSON_PRETTY() | 美化JSON格式 |
其他函数 | JSON_STORAGE_SIZE() | JSON文档占用的存储空间 |
其他函数 | JSON_STORAGE_FREE() | JSON文档更新操作后剩余的空间,MySQL8.0新增 |
其他函数 | JSON_TABLE() | 将JSON文档转换为表格,MySQL8.0新增 |
其他函数 | JSON_ARRAYAGG() | 讲聚合后参数中的多个值转换为JSON数组 |
其他函数 | JSON_OBJECTAGG() | 讲两个列或者是表达式解释为一个key和一个value,返回一个JSON对象 |
如上表格,JSON函数功能分为几类:
- 创建JSON函数
- 查询JSON函数
- 修改JSON函数
- 查询JSON元数据函数
- 其他函数
5.1.创建JSON函数
- JSON_ARRAY(val1, val2, ..., valn)函数,返回包含参数中所有值的JSON数组,参数中的null、true、false大小写不敏感。
sql
// 混合类型的JONS数组
mysql> select json_array(1, 'abc', "def", true, FALSE, null, NULL, now());
+--------------------------------------------------------------------------+
| json_array(1, 'abc', "def", true, FALSE, null, NULL, now()) |
+--------------------------------------------------------------------------+
| [1, "abc", "def", true, false, null, null, "2024-04-25 15:31:16.000000"] |
+--------------------------------------------------------------------------+
1 row in set (0.08 sec)
- JSON_OBJECT(key1, value1[, key2, value2] ..., keyn, valuen)函数,返回包含参数中所有键值对的对象,参数key不能为null,参数个数也不能为奇数(键值对成双成对),否则报语法错。
sql
mysql> select json_object('name', 'testmysql', 'age', 10);
+---------------------------------------------+
| json_object('name', 'testmysql', 'age', 10) |
+---------------------------------------------+
| {"age": 10, "name": "testmysql"} |
+---------------------------------------------+
1 row in set (0.00 sec)
- JSON_QUOTE(string)函数,将参数中的JSON文档转换为双引号引起来的字符串,如果文档包含双引号,则转换后的字符串自动加上转义字符"\",如下:
sql
mysql> select json_quote("{'name','testmysql'}"), json_quote('{"name","testmysql"}'), json_quote('[1,2,3]'), json_quote('"null"');
+------------------------------------+------------------------------------+-----------------------+----------------------+
| json_quote("{'name','testmysql'}") | json_quote('{"name","testmysql"}') | json_quote('[1,2,3]') | json_quote('"null"') |
+------------------------------------+------------------------------------+-----------------------+----------------------+
| "{'name','testmysql'}" | "{\"name\",\"testmysql\"}" | "[1,2,3]" | "\"null\"" |
+------------------------------------+------------------------------------+-----------------------+----------------------+
1 row in set (0.00 sec)
- JSON_UNQUOTE(string)函数,和上面的JSON_QUOTE()函数相反。
5.2.查询JSON函数
- JSON_CONTAINS(target, condidate, path)函数,其中第三个参数path是可选的。此函数可以查询指定的元素condidate是否包含在目标JSON文档target中,包含则返回1,否则返回0。如果参数为null或path(指定了path参数,path指向的值不存在),则返回null。
例如分别查询元素 "abc"、1、10 是否包含在JSON文档[1,2,3,"abc",null]中,如下:
sql
mysql> select json_contains('[1,2,3,"abc",null]', '"abc"');
+----------------------------------------------+
| json_contains('[1,2,3,"abc",null]', '"abc"') |
+----------------------------------------------+
| 1 |
+----------------------------------------------+
1 row in set (0.00 sec)
mysql> select json_contains('[1,2,3,"abc",null]', '1');
+------------------------------------------+
| json_contains('[1,2,3,"abc",null]', '1') |
+------------------------------------------+
| 1 |
+------------------------------------------+
1 row in set (0.00 sec)
mysql> select json_contains('[1,2,3,"abc",null]', '10');
+-------------------------------------------+
| json_contains('[1,2,3,"abc",null]', '10') |
+-------------------------------------------+
| 0 |
+-------------------------------------------+
1 row in set (0.00 sec)
mysql> select json_contains('[1,2,3,"abc",null]', 'null');
+---------------------------------------------+
| json_contains('[1,2,3,"abc",null]', 'null') |
+---------------------------------------------+
| 1 |
+---------------------------------------------+
1 row in set (0.00 sec)
mysql> select json_contains('[1,2,3,"abc",null]', null);
+-------------------------------------------+
| json_contains('[1,2,3,"abc",null]', null) |
+-------------------------------------------+
| NULL |
+-------------------------------------------+
1 row in set (0.00 sec)
要查找的元素如果是数组也是可以的:
sql
mysql> select json_contains('[1,2,3,"abc",null]', '[1,3]');
+----------------------------------------------+
| json_contains('[1,2,3,"abc",null]', '[1,3]') |
+----------------------------------------------+
| 1 |
+----------------------------------------------+
1 row in set (0.00 sec)
mysql> select json_contains('[1,2,3,"abc",null]', '[1,6]');
+----------------------------------------------+
| json_contains('[1,2,3,"abc",null]', '[1,6]') |
+----------------------------------------------+
| 0 |
+----------------------------------------------+
1 row in set (0.00 sec)
mysql> select json_contains('[1,2,3,"abc",null]', '[1,"abc"]');
+--------------------------------------------------+
| json_contains('[1,2,3,"abc",null]', '[1,"abc"]') |
+--------------------------------------------------+
| 1 |
+--------------------------------------------------+
1 row in set (0.00 sec)
刚才说path参数是可选的,path参数可以指定要查询的JSON文档路径(如果你懂的java中的jsonpath,那这里就明白了),例如要查询JSON文档 {"jack", 10, "tom", 20}中是否包含值为10的对象,同时指定path为$.jack(意思就是在key=jack的value条件下,判断是不是等于10)
sql
mysql> select json_contains(json_object("jack", 10, "tom", 20), '10', '$.jack');
+-------------------------------------------------------------------+
| json_contains(json_object("jack", 10, "tom", 20), '10', '$.jack') |
+-------------------------------------------------------------------+
| 1 |
+-------------------------------------------------------------------+
1 row in set (0.01 sec)
mysql> select json_contains(json_object("jack", 10, "tom", 20), '20', '$.tom');
+------------------------------------------------------------------+
| json_contains(json_object("jack", 10, "tom", 20), '20', '$.tom') |
+------------------------------------------------------------------+
| 1 |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
- JSON_EXTRACT(json_doc, path, ... path)函数,可以从JSON文档中抽取数据,如果参数有NULL或path不存在,则返回NULL。如果抽取出多个path,则返回的数据合并在一个JSON_ARRAY里。
sql
// 取文档的第一个和第二个元素
mysql> select json_extract('[1, 2, [3, 4]]', '$[0]', '$[1]');
+------------------------------------------------+
| json_extract('[1, 2, [3, 4]]', '$[0]', '$[1]') |
+------------------------------------------------+
| [1, 2] |
+------------------------------------------------+
1 row in set (0.00 sec)
// 取文档的第一个和第三个元素
mysql> select json_extract('[1, 2, [3, 4]]', '$[0]', '$[2]');
+------------------------------------------------+
| json_extract('[1, 2, [3, 4]]', '$[0]', '$[2]') |
+------------------------------------------------+
| [1, [3, 4]] |
+------------------------------------------------+
1 row in set (0.00 sec)
// 取文档的第三个元素
mysql> select json_extract('[1, 2, [3, 4]]', '$[2]');
+----------------------------------------+
| json_extract('[1, 2, [3, 4]]', '$[2]') |
+----------------------------------------+
| [3, 4] |
+----------------------------------------+
1 row in set (0.00 sec)
再看一个JSON对象属性的提取,如下:
sql
mysql> select json_extract('{"name":"test", "age":10}', '$.age');
+----------------------------------------------------+
| json_extract('{"name":"test", "age":10}', '$.age') |
+----------------------------------------------------+
| 10 |
+----------------------------------------------------+
1 row in set (0.00 sec)
MySQL 5.7.9版本之后,可以用简单的函数 "->" 和 "->>"来替代 JSON_EXTRACT,但是这种写法需要从表中JOSN字段获取,因为函数的左边需要指定列名(column->path),这里就不举例了。
- JSON_KEYS(json_doc, [path])函数,获取JSON文档在指定路径下的所有键值,返回一个JSON_ARRAY。如果有参数为NULL和path不存在,则返回NULL。
sql
mysql> select json_keys('{"name":"test", "age":10}');
+----------------------------------------+
| json_keys('{"name":"test", "age":10}') |
+----------------------------------------+
| ["age", "name"] |
+----------------------------------------+
1 row in set (0.01 sec)
如果JSON文档中的元素都是ARRAY,结果也是返回NULL。
- JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] ...])函数,查询包含指定字符串的路径,并作为一个JSON_ARRAY返回。如果有参数为NULL或path不存在,则返回NULL。
参数说明:
- json_doc: JSON 文档
- one_or_all: 搜索模式,可以是 'one' 或 'all'。'one' 表示返回第一个匹配的路径,'all' 表示返回所有 匹配路径的数组。
- search_str: 要搜索的字符串或 JSON 类型的值。
- escape_char: 用于转义路径中的特殊字符的字符。默认是 NULL,表示不使用转义。
- path: 可选参数,用于指定搜索的起始路径。
sql
// 使用 json_search 来搜索 "Ford" 这个值
mysql> SELECT JSON_SEARCH('{"name": "John", "age": 30, "cars": {"car1": "Ford", "car2": "BMW", "car3": "Fiat"}}', 'one', 'Ford');
+--------------------------------------------------------------------------------------------------------------------+
| JSON_SEARCH('{"name": "John", "age": 30, "cars": {"car1": "Ford", "car2": "BMW", "car3": "Fiat"}}', 'one', 'Ford') |
+--------------------------------------------------------------------------------------------------------------------+
| "$.cars.car1" |
+--------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
5.3.修改JSON的函数
- JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...)函数,可以在指定path的json array尾部追加val。如果指定path是一个json object,则将其封装成一个json array再追加。如果参数有NULL,则返回NULL。
sql
// 追加一个值
mysql> SELECT JSON_ARRAY_APPEND('{"numbers": [1, 2]}', '$.numbers', 3);
+----------------------------------------------------------+
| JSON_ARRAY_APPEND('{"numbers": [1, 2]}', '$.numbers', 3) |
+----------------------------------------------------------+
| {"numbers": [1, 2, 3]} |
+----------------------------------------------------------+
1 row in set (0.01 sec)
// 追加多个值
mysql> SELECT JSON_ARRAY_APPEND('{"numbers": [1, 2]}', '$.numbers', 3, '$.numbers', 4);
+--------------------------------------------------------------------------+
| JSON_ARRAY_APPEND('{"numbers": [1, 2]}', '$.numbers', 3, '$.numbers', 4) |
+--------------------------------------------------------------------------+
| {"numbers": [1, 2, 3, 4]} |
+--------------------------------------------------------------------------+
1 row in set (0.00 sec)
- JSON_ARRAY_INSERT(json_doc, path, val[, path, val]...)函数,可以在path指定的json array元素插入val,原位置以及以右的元素依次右移。如果path指定的数据非json array元素,则忽略此val。如果指定的元素下标超过json array的长度,则插入尾部。
sql
// 在索引为 2 的位置(原本为 4 的位置)插入一个值 3
mysql> SELECT JSON_ARRAY_INSERT('{"numbers": [1, 2, 4]}', '$.numbers[2]', 3);
+----------------------------------------------------------------+
| JSON_ARRAY_INSERT('{"numbers": [1, 2, 4]}', '$.numbers[2]', 3) |
+----------------------------------------------------------------+
| {"numbers": [1, 2, 3, 4]} |
+----------------------------------------------------------------+
1 row in set (0.00 sec)
- JSON_REPLACE(json_doc, path, val[, path, val]...)函数,可以替换指定路径的数据,如果某个path不存在,则忽略(存在才替换)。如果有参数为NULL,则返回NULL。
sql
// 想要替换 "age" 的值为 35,并添加一个新的键 "country",其值为 "USA"
mysql> SELECT JSON_REPLACE('{"name": "John", "age": 30, "city": "New York"}', '$.age', 35, '$.country', 'USA');
+--------------------------------------------------------------------------------------------------+
| JSON_REPLACE('{"name": "John", "age": 30, "city": "New York"}', '$.age', 35, '$.country', 'USA') |
+--------------------------------------------------------------------------------------------------+
| {"age": 35, "city": "New York", "name": "John"} |
+--------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
-
JSON_SET(json_doc, path, val[, path, val]...)函数,可以设置指定路径的数据,不管是否存在。如果参数存在NULL,则返回NULL。和上面的JSON REPLACE函数类似,最主要区别就是指定的路径存不存在。
-
JSON_MERGE_PRESERVE(json_doc, json_doc[, json_doc]...)函数,可以将多个JSON文档进行合并,合并规则如下:
- 如果都是json array,则结果自动merge为一个json array; - 如果都是json object,则结果自动merge为一个json object; - 如果多种类型,则将非json array的元素封装为json array再按照规则一进行merge。
sql
// 合并两个json文档
mysql> SELECT JSON_MERGE_PRESERVE('{"a": 1, "b": 2}', '{"b": 3, "c": 4}');
+-------------------------------------------------------------+
| JSON_MERGE_PRESERVE('{"a": 1, "b": 2}', '{"b": 3, "c": 4}') |
+-------------------------------------------------------------+
| {"a": 1, "b": [2, 3], "c": 4} |
+-------------------------------------------------------------+
1 row in set (0.00 sec)
- JSON_REMOVE(json_doc,path[, path]...)函数,可以移除指定路径的数据,如果路径不存在则忽略。如果有参数为NULL,则返回NULL。
sql
mysql> select json_remove('[1,2,3,4]', '$[1]', '$[2]');
+------------------------------------------+
| json_remove('[1,2,3,4]', '$[1]', '$[2]') |
+------------------------------------------+
| [1, 3] |
+------------------------------------------+
1 row in set (0.01 sec)
仔细看,如果按照理解不是删除了第二个和第三个元素,结果不应该是 1,4 嘛,但却是1,3。因为制定了多个path,删除操作是串行的,先删除第而个元素,结果是 1,3,4。然后在此基础上在删除第三个元素,也就是结果就是 1,3 了。
5.4.查询JSON元数据函数
- JSON_DEPTH(json_doc)函数,用来获取JSON文档的深度,如果JSON文档是空数组、空对象、null、true和false,则深度为1。如果非空数组或非空对象里面包含的都是深度为1的对象,则整个文档深度为2。以此类推,整个文档的深度取决于最大元素的深度。
sql
mysql> select json_depth(null), json_depth('[]'), json_depth('{"name":"test"}') test1 ,json_depth('{"name":"test", "hobby":[{"name":"篮球"}]}') test2;
+------------------+------------------+-------+-------+
| json_depth(null) | json_depth('[]') | test1 | test2 |
+------------------+------------------+-------+-------+
| NULL | 1 | 2 | 4 |
+------------------+------------------+-------+-------+
1 row in set (0.00 sec)
-
JSON_LENGTH(json_doc[, path])函数,获取指定路径下的文档长度,长度的计算规则如下:
- 标量(字符串、数字)的长度为1 - json array的长度为元素的个数 - json object的长度为元素的个数 - 嵌套数组或嵌套对象不计算长度
sql
mysql> select json_length(null), json_length('123456'), json_length('[1,2,3]'), json_length('{"name":"test"}');
+-------------------+-----------------------+------------------------+--------------------------------+
| json_length(null) | json_length('123456') | json_length('[1,2,3]') | json_length('{"name":"test"}') |
+-------------------+-----------------------+------------------------+--------------------------------+
| NULL | 1 | 3 | 1 |
+-------------------+-----------------------+------------------------+--------------------------------+
1 row in set (0.00 sec)
- JSON_TYPE(json_val)函数,获取JSON文档的类型,可以是数组、对象或标量类型。
sql
mysql> select json_type('[1,2]'), json_type('{"name":"test"}'), json_type('1'), json_type('"hi"'), json_type(null);
+--------------------+------------------------------+----------------+-------------------+-----------------+
| json_type('[1,2]') | json_type('{"name":"test"}') | json_type('1') | json_type('"hi"') | json_type(null) |
+--------------------+------------------------------+----------------+-------------------+-----------------+
| ARRAY | OBJECT | INTEGER | STRING | NULL |
+--------------------+------------------------------+----------------+-------------------+-----------------+
1 row in set (0.00 sec)
- JSON_VALID(json_val)函数,判断函数值val是否为有效的JSON格式,有效返回1,否则返回0.
sql
mysql> select json_valid('[123'), json_valid(null), json_valid('[1,2]');
+--------------------+------------------+---------------------+
| json_valid('[123') | json_valid(null) | json_valid('[1,2]') |
+--------------------+------------------+---------------------+
| 0 | NULL | 1 |
+--------------------+------------------+---------------------+
1 row in set (0.01 sec)
5.5.JSON工具函数
- JSON_PRETTY(json_val)函数,梅花JSON的输出格式。
sql
mysql> select json_pretty('[1,2,3]'), json_pretty('{"name":"test","age":10}');
+------------------------+-----------------------------------------+
| json_pretty('[1,2,3]') | json_pretty('{"name":"test","age":10}') |
+------------------------+-----------------------------------------+
| [
1,
2,
3
] | {
"age": 10,
"name": "test"
} |
+------------------------+-----------------------------------------+
1 row in set (0.00 sec)
-
JSON_STORAGE_SIZE(json_val) / JSON_STORAGE_FREE(json_val)函数,分别获取JSON文档占用的存储空间(byte)和由于JSON_SET、JSON_REPLACE、JSON_REMOVE操作导致释放的空间。
-
JSON_TABLE(expr, path COLUMNS (column_list) [AS] alias)函数,将JSON文档映射为表格。参数expr可以是表达式或者列。path是用来过滤的JSON路径。COLUMNS是常量关键字。column list是转换后的字段列表。
这个函数可以将复杂的JSON文档转换为表格数据,转换后可以向正常表一样做链接、排序等各种操作。
- JSON_ARRAYAGG(col_or_expr)函数,将聚合后参数中的多个值转换为JSON数组 或 将一组值转换为JSON数组。它接受一个参数,即要转换为数组的列名或表达式,并返回JSON格式的字符串。
- JSON_OBJECTAGG(key, value)函数,将两个列或表达式解释为一个key和一个value,返回一个JSON对象。
6.窗口函数
MySQL 8.0 引入了窗口函数(Window Functions),它们允许用户执行计算跨行集(称为窗口)的操作,而不是仅针对单行。窗口函数通常与 OVER() 子句一起使用,该子句定义了窗口的范围以及窗口如何沿着结果集移动。
窗口函数非常有用,尤其是在进行如累计总和、移动平均、排名等计算时。
以下是一些常见的 MySQL 窗口函数:
- ROW_NUMBER():为结果集中的每一行分配一个唯一的序号。
sql
SELECT name, age, ROW_NUMBER() OVER (ORDER BY age DESC) as rank FROM users;
- RANK() 和 DENSE_RANK():为结果集中的每一行分配一个排名。RANK() 在遇到相同的值时会跳过下一个排名,而 DENSE_RANK() 则不会。
sql
SELECT name, score, RANK() OVER (ORDER BY score DESC) as rank FROM scores;
- NTILE(n):将结果集分成大致相等的 n 个部分,并为每一行分配一个桶号。
sql
SELECT name, score, NTILE(4) OVER (ORDER BY score DESC) as quartile FROM scores;
- LEAD() 和 LAG():获取结果集中当前行之前或之后的行的值。
sql
SELECT date, sales,
LAG(sales) OVER (ORDER BY date) as previous_day_sales,
LEAD(sales) OVER (ORDER BY date) as next_day_sales
FROM sales_data;
- FIRST_VALUE() 和 LAST_VALUE():获取窗口范围内的第一个或最后一个值。
sql
SELECT date, sales,
FIRST_VALUE(sales) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as first_sales_in_window,
LAST_VALUE(sales) OVER (ORDER BY date ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) as last_sales_in_window
FROM sales_data;
- SUM(), AVG(), MIN(), MAX() 等聚合函数也可以用作窗口函数。例如,计算累计总和:
sql
SELECT date, sales, SUM(sales) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as cumulative_sales
FROM sales_data;
使用窗口函数时,你可以通过 PARTITION BY 子句将数据分成多个分区,并为每个分区独立地计算窗口函数。这允许你在每个分区内进行排名、累计等计算。
请注意,为了使用窗口函数,你的 MySQL 服务器版本必须是 8.0 或更高。在早期的 MySQL 版本中,这些功能是不可用的。
7.其他函数
除了前面的函数,还有很多函数,就不一一列举了,这里说一些其他的函数。
函数 | 功能 |
---|---|
DATABASE() | 返回当前数据库名 |
VERSION() | 返回当前数据库版本 |
USER() | 返回当前登录用户名 |
INET_ATON(IP) | 返回IP地址的数字表示 |
INET_NTOA(num) | 返回数字代表的IP地址 |
PASSWORD(str) | 返回字符串str的加密版本 |
MD5(str) | 返回字符串str的MD5值 |