语法
GROUP_CONCAT
GROUP_CONCAT的作用是将结果结合成字符串,
示例:
除了名字不一样,其它都一样,现在需要将名字逗号拼接

SELECT
v.vehicle_no,
GROUP_CONCAT(d.driver_name ORDER BY d.driver_name SEPARATOR ', ') AS driver_names,
CONCAT(m.brand,m.model),
-- 如果这个值是空的,显示为否
IFNULL(v.register_date, "否") AS register_date,
-- 值判断,switch效果
CASE
WHEN v.vehicle_type = 1 THEN "小型普通客车"
WHEN v.vehicle_type = 2 THEN "小型轿车"
WHEN v.vehicle_type = 3 THEN "小型越野客车"
END AS vehicle_type
FROM
cc_vehicle v
LEFT JOIN cc_vehicle_driver d ON v.id = d.vehicle_id
LEFT JOIN cc_vehicle_model m ON m.id = v.model_id
GROUP BY
v.id, v.vehicle_no, m.brand, m.model, v.register_date, v.vehicle_type
效果:

默认用逗号分隔
select GROUP_CONCAT(user_name) from score1

指定分隔符号
select GROUP_CONCAT(user_name separator ';') from score1

结果去重
select GROUP_CONCAT(distinct user_name) from score1

倒序排列
select GROUP_CONCAT(user_name ORDER BY user_name desc) from score1

按照名称分组
select GROUP_CONCAT(user_name) from score1 GROUP BY user_name

注意事项
1. 长度限制(group_concat_max_len)
- MySQL 默认限制拼接结果长度(默认 1024 字节 ,可通过
SHOW VARIABLES LIKE 'group_concat_max_len';查看)。 - 若拼接内容超长,结果会被 截断 !解决方法:
-- 临时生效(当前会话) SET SESSION group_concat_max_len = 102400; -- 永久生效(需修改配置文件,重启服务) # 在 my.cnf 或 my.ini 中添加 group_concat_max_len = 102400
2. 性能影响
- 处理 超大量数据 时,拼接操作会消耗较多内存和 CPU,可能拖慢查询。
- 优化建议:
- 尽量缩小查询范围(用
WHERE过滤不必要数据); - 避免嵌套复杂表达式,简化拼接逻辑;
- 确认是否真的需要合并所有数据,而非分开展示。
- 尽量缩小查询范围(用
cast
CAST函数语法规则是:Cast(字段名 as 转换的类型 ),其中类型可以为:
CHAR[(N)] 字符型
DATE 日期型
DATETIME 日期和时间型
DECIMAL float型
SIGNED int
TIME 时间型
把data字段转为signed类型
select cast(date as signed) as date from table1;
left
LEFT()函数是一个字符串函数,它返回具有指定长度的字符串的左边部分,
从左往右返回2位长度字符
select left('张三李四',2)

时间相关函数
- NOW()
获取当前时间
select NOW() 当前时间和时间,CURDATE() 当前日期,CURTIME() 当前时间 FROM dual

DATE_SUB
从日期减去指定的时间间隔DATE_SUB(date,INTERVAL expr type)
- 三个月内的数据
当前时间往前三个月内的数据
SELECT *
FROM your_table
WHERE date_column >= DATE_SUB(NOW(), INTERVAL 3 MONTH);
DATE_ADD
从日期增加指定的时间间隔DATE_ADD(date,INTERVAL expr type)
- 未来三个月内的数据
当前时间未来三个月内的数据
SELECT *
FROM your_table
WHERE date_column >= NOW()
AND date_column < DATE_ADD(NOW(), INTERVAL 3 MONTH);
DATE
DATE函数,将日期转为年月日DATE('2024-11-6 15:05:05')=2024-11-6
select * from user where DATE(create_time)=DATE('2024-11-6 15:05:05')
IF
判断a是否等于b,相等返回true,不相等返回fasle
select if(a=b,'true','false') result from dual
死锁
information_schema.INNODB_TRX
需要管理员权限
SELECT * FROM information_schema.INNODB_TRX
在执行结果中可以看到是否有表锁等待或者死锁,如果有死锁发生,可以通过下面的命令来杀掉当前运行的事务:
KILL 165667
show status like 'innodb_row_lock%'
Innodb_row_lock_current_waits : 当前等待锁的数量
Innodb_row_lock_time : 系统启动到现在,锁定的总时间长度
Innodb_row_lock_time_avg : 每次平均锁定的时间
Innodb_row_lock_time_max : 最长一次锁定时间
Innodb_row_lock_waits : 系统启动到现在总共锁定的次数
+----------------------------+---------------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------------------+---------------------+------+-----+---------------------+-------+
| trx_id | varchar(18) | NO | | | |#事务ID
| trx_state | varchar(13) | NO | | | |#事务状态:
| trx_started | datetime | NO | | 0000-00-00 00:00:00 ||#事务开始时间;
| trx_requested_lock_id | varchar(81) | YES | | NULL ||#innodb_locks.lock_id
| trx_wait_started | datetime | YES | | NULL | |#事务开始等待的时间
| trx_weight | bigint(21) unsigned | NO | | 0 | |#事务的权重,反应一个事务修改和锁定的行数,当发现死锁需要回滚时,权重越小的值被回滚
| trx_mysql_thread_id | bigint(21) unsigned | NO | | 0 ||#事务线程ID
| trx_query | varchar(1024) | YES | | NULL | |#具体SQL语句
| trx_operation_state | varchar(64) | YES | | NULL ||#事务当前操作状态
| trx_tables_in_use | bigint(21) unsigned | NO | | 0 ||#事务中有多少个表被使用
| trx_tables_locked | bigint(21) unsigned | NO | | 0 ||#事务拥有多少个锁
| trx_lock_structs | bigint(21) unsigned | NO | | 0 | |#
| trx_lock_memory_bytes | bigint(21) unsigned | NO | | 0 ||#事务锁住的内存大小(B)
| trx_rows_locked | bigint(21) unsigned | NO | | 0 ||#事务锁住的行数
| trx_rows_modified | bigint(21) unsigned | NO | | 0 ||#事务更改的行数
| trx_concurrency_tickets | bigint(21) unsigned | NO | | 0 ||#事务并发票数
| trx_isolation_level | varchar(16) | NO | | | |#事务隔离级别
| trx_unique_checks | int(1) | NO | | 0 | |#是否唯一性检查
| trx_foreign_key_checks | int(1) | NO | | 0 | |#是否外键检查
| trx_last_foreign_key_error | varchar(256) | YES | | NULL ||#最后的外键错误
| trx_adaptive_hash_latched | int(1) | NO | | 0 | |#
| trx_adaptive_hash_timeout | bigint(21) unsigned | NO | | 0 ||#
暴力解决
KILL 165667 ; KILL 后面的数字指的是 trx_mysql_thread_id 值
trx_mysql_thread_id:MySQL中的进程ID,与show processlist中的ID值相对应
trx_query:事务运行的SQL语句
死锁表
select * from performance_schema.data_locks;
+-------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------------+------+-----+---------+-------+
| lock_id | varchar(81) | NO | | | |#锁ID
| lock_trx_id | varchar(18) | NO | | | |#拥有锁的事务ID
| lock_mode | varchar(32) | NO | | | |#锁模式
| lock_type | varchar(32) | NO | | | |#锁类型
| lock_table | varchar(1024) | NO | | | |#被锁的表
| lock_index | varchar(1024) | YES | | NULL | |#被锁的索引
| lock_space | bigint(21) unsigned | YES | | NULL | |#被锁的表空间号
| lock_page | bigint(21) unsigned | YES | | NULL | |#被锁的页号
| lock_rec | bigint(21) unsigned | YES | | NULL | |#被锁的记录号
| lock_data | varchar(8192) | YES | | NULL | |#被锁的数据
# 查询死锁等待时间
select * from sys.innodb_lock_waits;
locked_table : 哪张表出现的等待
waiting_trx_id: 等待的事务(与上个视图trx_id 对应)
waiting_pid : 等待的线程号(与上个视图trx_mysql_thread_id)
blocking_trx_id : 当前拥有锁的事务ID
blocking_pid : 当前拥有锁的锁ID
死锁的排查
未提交的事务
processlist中未提交的事务
show processlist
根据INNODB_TRX中的trx_mysql_thread_id查询进程明细,host为客户端ip段进口
SELECT * FROM information_schema.processlist where id=4086

未提交事务的Command为Sleep,State为空,Info为NULL
information_schema.innodb_trx中的未提交事务
information_schema.innodb_trx.trx_query为NULL,无法提供未提交事务的SQL语句
SELECT * FROM information_schema.INNODB_TRX

performance_schema.events_statements_current中的未提交事务
select * from performance_schema.events_statements_current
where sql_text not like 'select * from performance_schema.events_statements_current%'
一个事务可能有一组sql组成,这个方法只能看到事务最后执行的是什么SQL,无法看到全部。可以通过performance_schema.threads表来关联,将information_schema.processlist和performance_schema.events_statements_current一一对应起来
select t1.id, t2.thread_id, t3.sql_text from information_schema.processlist t1,performance_schema.threads t2,performance_schema.events_statements_current t3
where t1.id=4806 and t1.id=t2.processlist_id and t2.thread_id = t3.thread_id
如果没有死锁,并且状态一直是running,running了很久,可能是事物没有设置回滚,
select * from information_schema.`PROCESSLIST` where id in (SELECT trx_mysql_thread_id from information_schema.INNODB_TRX where trx_state='RUNNING')

事务一直running
#查看日志状态
show variables like 'general_log';
#设置是否开启日志
set global general_log=off;
#设置日志记录方式 table、file
set global log_output='table'
#根据thread_id查sql
SELECT *,CONVERT (argument USING utf8) as `sql` from mysql.general_log where thread_id = 17 ORDER BY event_time DESC;
# 清空日志表
truncate table mysql.general_log
死锁日志
show engine innodb status
# 这行表示事务id为3105550,事务处于活跃状态9s,starting index read表示正在使用索引读取数据行
---TRANSACTION 3105550, ACTIVE 9 sec starting index read
#这行表示该事务正在使用1个表,且涉及锁的表有1个
mysql tables in use 1, locked 1
# 这行表示在等待3把锁,占用内存1136字节,涉及1行记录
LOCK WAIT 3 lock struct(s), heap size 1136, 1 row lock(s), undo log entries 22
# 这行表示该事务的线程ID信息,操作系统句柄信息,连接来源、用户
MySQL thread id 5809, OS thread handle 140507283683072, query id 3017641 192.168.0.0.1 ztb_gansu updating
# 这行表示事务执行的最后一条SQL信息
update yw_bd set ab=null, address=null, aqwmcsf=null, bdcode='BD2022001875', bdfl=null, bdname='zzzzzz', bgplabdid=null, bjfs=null, bzjjnfs='', bzjkhh='', bzjyh='', bzjzh='', cbjsj=null, cgdwlxdh='18100001111', cgdwlxr='1', cgdwztid='1', cgdwztname='1', cglx=null, cgpmcodes=null, cgpmnames=null, cjryhl=null, content=null, cretime=null, currency=null, extinfo='{"extZjsjYear":{"remark":"最近一个数据审计年","value":"2022"},"extSfsjssgsgy":{"remark":"是否涉及上市公司国有股权间接转让","value":"0"},"extSfcztxqlr":{"remark":"是否存在他项权利人","value":"1"},"extJzrsj
Trx read view will not see trx with id >= 3105550, sees < 3100092
------- TRX HAS BEEN WAITING 9 SEC FOR THIS LOCK TO BE GRANTED:
# 这行信息表示等待的锁是一个record lock,空间id是503 ,页编号为64 ,大概位置在页的80位处,锁发生在表ztb_gansu.test_tb的yw_bd索引上,是一个X锁,但是不是gap lock,waiting表示正在等待锁
RECORD LOCKS space id 503 page no 64 n bits 80 index PRIMARY of table `ztb_gansu`.`yw_bd` trx id 3105550 lock_mode X locks rec but not gap waiting
Record lock, heap no 8 PHYSICAL RECORD: n_fields 96; compact format; info bits 0
0: len 30; hex 613935616661346235393365343034336135316230373337383764323039; asc a95afa4b593e4043a51b073787d209; (total 32 bytes);
1: len 6; hex 0000002f589e; asc /X ;;
2: len 7; hex 02000000ee23e7; asc # ;;
3: len 30; hex 643162323764333863633465343935656139316230353930396131623463; asc d1b27d38cc4e495ea91b05909a1b4c; (total 32 bytes);
4: SQL NULL;
5: len 5; hex 99ae374146; asc 7AF;;
6: len 7; hex 61616161616161; asc aaaaaaa;;
7: len 12; hex 424432303232303031383735; asc BD2022001875;;
8: len 11; hex 8000000000000001000000; asc ;;
9: SQL NULL;
10: SQL NULL;
11: len 0; hex ; asc ;;
12: len 0; hex ; asc ;;
13: len 1; hex 31; asc 1;;
14: len 11; hex 3138313030303031313131; asc 18100001111;;
15: SQL NULL;
16: SQL NULL;
17: SQL NULL;
18: SQL NULL;
19: len 1; hex 30; asc 0;;
20: SQL NULL;
21: SQL NULL;
22: SQL NULL;
23: SQL NULL;
24: SQL NULL;
25: SQL NULL;
26: SQL NULL;
27: SQL NULL;
28: SQL NULL;
29: SQL NULL;
30: SQL NULL;
31: SQL NULL;
32: SQL NULL;
33: SQL NULL;
34: SQL NULL;
35: SQL NULL;
36: SQL NULL;
37: SQL NULL;
38: len 1; hex 31; asc 1;;
39: len 1; hex 31; asc 1;;
40: SQL NULL;
41: SQL NULL;
42: SQL NULL;
43: SQL NULL;
44: SQL NULL;
45: SQL NULL;
46: SQL NULL;
47: SQL NULL;
48: SQL NULL;
49: SQL NULL;
50: SQL NULL;
51: SQL NULL;
52: SQL NULL;
53: SQL NULL;
54: SQL NULL;
55: SQL NULL;
56: SQL NULL;
57: SQL NULL;
58: SQL NULL;
59: SQL NULL;
60: SQL NULL;
61: SQL NULL;
62: SQL NULL;
63: SQL NULL;
64: SQL NULL;
65: SQL NULL;
66: SQL NULL;
67: SQL NULL;
68: SQL NULL;
69: SQL NULL;
70: SQL NULL;
71: SQL NULL;
72: SQL NULL;
73: SQL NULL;
74: SQL NULL;
75: SQL NULL;
76: SQL NULL;
77: SQL NULL;
78: SQL NULL;
79: SQL NULL;
80: SQL NULL;
81: SQL NULL;
82: len 1; hex 31; asc 1;;
83: SQL NULL;
84: SQL NULL;
85: len 11; hex 8000000000000001000000; asc ;;
86: len 1; hex 30; asc 0;;
87: SQL NULL;
88: len 4; hex 46584a4a; asc FXJJ;;
89: len 3; hex 4f4e45; asc ONE;;
90: SQL NULL;
91: SQL NULL;
92: len 0; hex ; asc ;;
93: len 0; hex ; asc ;;
94: SQL NULL;
95: len 30; hex 002900170c23010600290106002f010700360107003d010700440107004b; asc ) # ) / 6 = D K; (total 3096 bytes);
------------------
# 事物3103156,活跃2619s
---TRANSACTION 3103156, ACTIVE 2619 sec
# 等待1把锁,内存1136,涉及一行数据
1 lock struct(s), heap size 1136, 1 row lock(s)
# 线程id 5804,以及ip和用户
MySQL thread id 5804, OS thread handle 140510655903488, query id 2996772 192.168.0.0.1 root
---TRANSACTION 3103114, ACTIVE 2660 sec
2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 5796, OS thread handle 140507265332992, query id 2996402 192.168.0.0.1 root
---TRANSACTION 3101888, ACTIVE 3665 sec
1 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 5776, OS thread handle 140510624380672, query id 2987217 192.168.0.0.1 root
---TRANSACTION 3101267, ACTIVE 4349 sec
1 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 5770, OS thread handle 140519116973824, query id 2989155 192.168.0.0.1 root
---TRANSACTION 3101247, ACTIVE 4375 sec
1 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 5769, OS thread handle 140507283977984, query id 2981788 192.168.0.0.1 root
---TRANSACTION 3100092, ACTIVE 5668 sec
2 lock struct(s), heap size 1136, 1 row lock(s), undo log entries 1
MySQL thread id 5749, OS thread handle 140520111859456, query id 2971455 192.168.0.0.1 root
错误
zhangsan这个用户没有user表的权限
SELECT command denied to user 'zhangsan'@'192.168.0.79' for table 'user'
查看sql记录
一、mysql查看正在执行的sql语句
show processlist;
二、mysql查看已经执行的历史sql语句(方法:开启日志模式)
-- 查看日志功能设置状态
show variables like 'general_log';
-- 查看当前日志输出类型:默认file
show variables like 'log_output';
-- 打开日志记录功能
set global general_log=on;
-- 关闭日志记录功能
set global general_log=off;
-- 设置日志输出至table
set global log_output='table';
-- 日志输出至table模式,查看日志记录
SELECT * from mysql.general_log ORDER BY event_time DESC;
-- 设置日志输出至file
set global log_output='file';
-- 查看日志输出文件的保存路径
show variables like 'general_log_file';
-- 修改日志输出文件的保存路径
set global general_log_file='tmp/general.log';
-- 日志输出至table模式,清空日志记录
truncate table mysql.general_log;
-- 日志输出至file模式,查看日志记录
cat /tmp/general.log
默认文件位置:/home/root/mysql/data/mysql/general_log.CSV
注意:在查询到所需要的记录之后,应尽快关闭日志模式,占用磁盘空间比较大
查看当前数据库的连接数量
最大连接数量
show VARIABLES like 'max_connections'

当前连接数
SHOW STATUS LIKE 'Threads_connected';

断开一个后查看

连接信息
show status like ‘%connect%’;

查询当前所有连接
show full processlist;

SHOW FULL PROCESSLIST 是 MySQL 中一个非常有用的命令,用于显示当前正在运行的所有线程及其详细信息。这个命令可以帮助你诊断数据库性能问题、识别长时间运行的查询以及了解数据库的当前活动状态。
命令语法
SHOW FULL PROCESSLIST;
输出字段解释
执行 SHOW FULL PROCESSLIST 命令后,你会看到一个包含多个字段的结果集。以下是各个字段的详细解释:
-
Id:
- 描述:每个连接的唯一标识符。
- 用途:用于标识特定的连接,可以用于
KILL命令终止某个连接。
-
User:
- 描述:执行查询的用户名。
- 用途:帮助你了解哪个用户正在执行查询。
-
Host:
- 描述:客户端的主机名或 IP 地址及端口号。
- 用途:帮助你了解查询是从哪个客户端发起的。
-
db:
- 描述:当前连接正在使用的数据库名称。
- 用途:帮助你了解查询是在哪个数据库中执行的。
-
Command:
- 描述:当前连接的状态或命令类型。
- 常见值:
Sleep:连接处于空闲状态。Query:正在执行查询。Connect:正在建立连接。Init DB:初始化数据库。Field List:请求字段列表。Prepare:准备执行 SQL 语句。Execute:执行 SQL 语句。Close stmt:关闭准备好的语句。Fetch:获取结果集的一部分。Ping:检查连接是否仍然有效。Quit:断开连接。Daemon:后台线程。
-
Time:
- 描述:连接处于当前状态的时间(以秒为单位)。
- 用途:帮助你识别长时间运行的查询。
-
State:
- 描述:当前连接的详细状态。
- 常见值:
starting:连接刚刚开始。checking permissions:检查权限。Opening tables:打开表。System lock:等待系统锁。init:初始化查询。updating:更新数据。query end:查询结束。freeing items:释放资源。cleaning up:清理连接。Sending data:发送数据。Sorting result:排序结果。Writing to net:写入网络。end:结束。
-
Info:
- 描述:当前执行的 SQL 语句。
- 用途:帮助你了解具体的查询内容。
- 使用场景
-
识别长时间运行的查询:
- 查找
Time字段值较大的行,这些行可能是导致性能问题的原因。
- 查找
-
终止特定连接:
- 使用
KILL命令终止特定的连接。例如,终止 ID 为 2 的连接:KILL 2;
- 使用
-
监控数据库活动:
- 定期运行
SHOW FULL PROCESSLIST命令,监控数据库的活动情况,确保没有异常的查询或连接。
- 定期运行
-
调试查询:
- 查看
Info字段中的 SQL 语句,帮助你调试和优化查询。
- 查看
注意事项
- 权限:只有具有
PROCESS权限的用户才能看到所有连接的信息。普通用户只能看到自己的连接。 - 性能影响:频繁执行
SHOW FULL PROCESSLIST可能会对数据库性能产生轻微影响,因此建议在必要时使用。
查看连接创建的时间
并没有直接显示创建连接的字段,需要当前时间减去运行时长,得到创建时间
SELECT
Id,
User,
Host,
db,
Command,
Time,
State,
Info,
CURRENT_TIMESTAMP() - INTERVAL Time SECOND AS Connect_Time
FROM
INFORMATION_SCHEMA.PROCESSLIST;

查看表信息
查询所有表信息
SELECT
*
FROM
INFORMATION_SCHEMA.TABLES
查看表名和表注释
查看表名包括user的表名和注释
SELECT
TABLE_NAME AS '表名',
TABLE_COMMENT AS '表注释'
FROM
INFORMATION_SCHEMA.TABLES
where table_name like '%user%'
查看字段信息
SELECT
column_name '字段名',
column_comment '字段注释'
FROM
INFORMATION_SCHEMA.COLUMNS
where table_name = '表名'
数据格式为JSON

JSON_EXTRACT查询
查询json中code为4的数据,需要注意的是4如果为int类型,就不能加引号
select * from user where JSON_EXTRACT(param,"$.code") = 4 and JSON_EXTRACT(param,"$.desc") like '%全%'
还有一种简化的写法
select * from user where param ->"$.code" = 4 and param -> "$.desc" like '%全%'
多条件用and拼接,精确匹配用=,模糊用like

还有一种简化的写法
select * from user where param ->"$.code" = 4 and param -> "$.desc" like '%全%'
JSON_CONTAINS查询
JSON_OBJECT就是将里面的参数组成对象形式
JSON_CONTAINS会将JSON型的数组也查询
select * from user where JSON_CONTAINS(param, JSON_OBJECT('code',4))

- 满足这个json的code=1,desc=行驶证到期,才能查到
select * from user where JSON_CONTAINS(param, JSON_OBJECT('code',1,'desc','行驶证到期'))

- 这个数组必须同时包含code=1和code=2
select * from user where JSON_CONTAINS(param, JSON_OBJECT('code',1)) and JSON_CONTAINS(param, JSON_OBJECT('code',2))

- 模糊查询
- 只查询数组,数组中,所有json只要desc模糊包含全的数据
select * from user where param -> '$[*].desc' like '%全%'
- 查询数组,下标为0的(普通json也算下标为0),desc模糊包含全的数据
select * from user where param -> '$[0].desc' like '%全%'
- 只查询数组,数组中,所有json只要desc模糊包含全的数据
查询多层嵌套
查询json中,第一层包含desc and desc中包含msg and msg包含code的数据
SELECT *
FROM user
WHERE JSON_EXTRACT(param, '$.desc.msg.code')

查询json中,第一层为desc and desc中包含msg and msg包含code,并且code=5
的数据
SELECT *
FROM user
WHERE JSON_EXTRACT(param, '$.desc.msg.code') = 5;

模糊查询多层级
select * from user where param-> '$**.code' like '%4%'

查询指定key对应的value
查询key为platform的value值
SELECT
JSON_EXTRACT(u.param, '$[*].platform') AS platform_values
FROM user u where JSON_EXTRACT(u.param, '$[*].platform') is not null

$[]和$
$[*]代表筛选json型的数组,key的值为platform的数据
select * from user where JSON_EXTRACT(param, '$[*].platform')
$[0]代表筛选json型的数组,下标为0的,key的值为platform的数据
select * from user where JSON_EXTRACT(param, '$[0].platform')
$代表筛选json型的,key的值为code的数据
select * from user where JSON_EXTRACT(param, '$.code')
JSON_MERGE_PATCH
这个函数用来新增JSON数据中的字段,而不影响其它字段。
如果键名相同,会覆盖原值,如果键名不相同,则会新增到json中
-
示例
SELECT JSON_MERGE_PATCH('{"name": "Alice", "age": 30, "city": "Beijing"}', '{"age": 35, "country": "China"}') AS merged_json;结果
{"age": 35, "city": "Beijing", "name": "Alice", "country": "China"}
JSON_SET
修改指定key的值
SELECT JSON_SET('{"name": "Alice", "age": 30}', '$.age', 35) AS set_age;
age改为35

JSON_REMOVE
移除json中指定的值
select JSON_REMOVE('{"Flag": 1, "State": 0}', '$.Flag')
移除Flag

运算符、符号、函数
1. 算术运算符
| 符号 | 描述 | 示例 |
|---|---|---|
+ | 加法 | SELECT 5 + 3; |
- | 减法 | SELECT 5 - 3; |
* | 乘法 | SELECT 5 * 3; |
/ | 除法 | SELECT 5 / 3; |
% | 取模(取余数) | SELECT 5 % 3; |
2. 比较运算符
| 符号 | 描述 | 示例 |
|---|---|---|
= | 等于 | SELECT * FROM users WHERE id = 1; |
<> 或 != | 不等于 | SELECT * FROM users WHERE id != 1; |
< | 小于 | SELECT * FROM users WHERE age < 30; |
> | 大于 | SELECT * FROM users WHERE age > 30; |
<= | 小于或等于 | SELECT * FROM users WHERE age <= 30; |
>= | 大于或等于 | SELECT * FROM users WHERE age >= 30; |
BETWEEN | 在两个值之间 | SELECT * FROM users WHERE age BETWEEN 20 AND 30; |
IN | 在指定的集合中 | SELECT * FROM users WHERE id IN (1, 2, 3); |
LIKE | 模糊匹配 | SELECT * FROM users WHERE name LIKE 'A%'; |
IS NULL | 是否为空 | SELECT * FROM users WHERE address IS NULL; |
3. 逻辑运算符
| 符号 | 描述 | 示例 |
|---|---|---|
AND | 逻辑与 | SELECT * FROM users WHERE age > 20 AND age < 30; |
OR | 逻辑或 | SELECT * FROM users WHERE age < 20 OR age > 30; |
NOT | 逻辑非 | SELECT * FROM users WHERE NOT age = 25; |
4. 聚合函数
虽然严格来说不是符号,但聚合函数是查询中常用的工具。
| 函数 | 描述 | 示例 |
|---|---|---|
COUNT() | 计数 | SELECT COUNT(*) FROM users; |
SUM() | 求和 | SELECT SUM(salary) FROM employees; |
AVG() | 平均值 | SELECT AVG(salary) FROM employees; |
MAX() | 最大值 | SELECT MAX(salary) FROM employees; |
MIN() | 最小值 | SELECT MIN(salary) FROM employees; |
5. 字符串函数
| 函数 | 描述 | 示例 |
|---|---|---|
CONCAT() | 连接字符串 | SELECT CONCAT(first_name, ' ', last_name) FROM users; |
SUBSTRING() | 提取子字符串 | SELECT SUBSTRING(name, 1, 3) FROM users; |
LENGTH() | 获取字符串长度 | SELECT LENGTH(name) FROM users; |
UPPER() | 将字符串转换为大写 | SELECT UPPER(name) FROM users; |
LOWER() | 将字符串转换为小写 | SELECT LOWER(name) FROM users; |
TRIM() | 去除首尾空格 | SELECT TRIM(name) FROM users; |
REPLACE() | 替换字符串中的子串 | SELECT REPLACE(email, 'old.com', 'new.com') FROM users; |
RIGHT() | 提取最右边的字符 | SELECT RIGHT(phone, 4) FROM contacts; |
LEFT() | 提取最左边的字符 | SELECT LEFT(phone, 3) FROM contacts; |
6. 日期和时间函数
| 函数 | 描述 | 示例 |
|---|---|---|
NOW() | 返回当前日期和时间 | SELECT NOW(); |
CURDATE() | 返回当前日期 | SELECT CURDATE(); |
CURTIME() | 返回当前时间 | SELECT CURTIME(); |
DATE() | 提取日期部分 | SELECT DATE(order_date) FROM orders; |
TIME() | 提取时间部分 | SELECT TIME(order_time) FROM orders; |
YEAR() | 提取年份 | SELECT YEAR(order_date) FROM orders; |
MONTH() | 提取月份 | SELECT MONTH(order_date) FROM orders; |
DAY() | 提取日 | SELECT DAY(order_date) FROM orders; |
DATEDIFF() | 计算两个日期之间的天数差 | SELECT DATEDIFF(date1, date2) FROM dates; |
7. 其他符号
| 符号 | 描述 | 示例 |
|---|---|---|
* | 所有列 | SELECT * FROM users; |
, | 列分隔符 | SELECT id, name FROM users; |
. | 表达式中的属性访问 | SELECT users.name FROM users; |
AS | 别名 | SELECT name AS full_name FROM users; |
() | 分组表达式 | SELECT (price * quantity) AS total FROM orders; |
FIND_IN_SET函数
某个值是否存在于一个逗号分隔的字符串列表中,并返回其位置(索引从 1 开始)。如果不存在,返回 0。
- 语法
FIND_IN_SET(待查找的值, 逗号分隔的字符串)
1. 基础用法:判断元素是否存在
假设有表 users,hobbies 字段存储用户爱好(逗号分隔):
| id | name | hobbies |
|---|---|---|
| 1 | 小明 | 篮球,足球,游泳 |
| 2 | 小红 | 唱歌,绘画 |
查询爱好包含“足球”的用户:
SELECT *
FROM users
WHERE FIND_IN_SET('足球', hobbies) > 0; -- 返回位置大于0表示存在
结果:
| id | name | hobbies |
|---|---|---|
| 1 | 小明 | 篮球,足球,游泳 |
2. 结合聚合函数:统计出现次数
统计所有用户中“游泳”作为爱好的人数:
SELECT
COUNT(*) AS swim_count
FROM users
WHERE FIND_IN_SET('游泳', hobbies) > 0;
3. 模糊匹配陷阱(重点!)
错误示例:查找包含 '1' 的记录:
-- 假设 tags 字段值为 '10,20,30'
SELECT *
FROM posts
WHERE FIND_IN_SET('1', tags) > 0; -- 结果为0(不匹配)
原因:FIND_IN_SET 严格匹配 完整元素,而非子串。'1' 与 '10' 是不同元素。
其它
随机四位整数
介于1000到9999之间
SELECT FLOOR(1000 + RAND() * 9000) AS random_number from dual;
- 金额处理
数据库存储类型为int型,单位分,除以100,就是元,
直接除的话是小数点后4位
select 1200/100 from dual

保留两位
select FORMAT(1200/100,2) from dual

计算两个时间差异
SELECT * FROM oc_wyc_order
WHERE TIMESTAMPDIFF(MINUTE, create_time, NOW()) <= 30;
TIMESTAMPDIFF(MINUTE, create_time, NOW()):
如果create_time小于now,就是正数,否则负数
TIMESTAMPDIFF 是一个 MySQL 函数,用于计算两个日期/时间之间的差异。
MINUTE 参数指定了计算的时间单位为分钟。
create_time 是表中创建时间的列名。
NOW() 是一个 MySQL 函数,返回当前的日期和时间。
条件表示计算的结果必须小于等于30分钟。
手动事务
-- 开启事务
START TRANSACTION;
-- 或者使用 BEGIN 替代 START TRANSACTION
-- BEGIN;
-- 执行你的SQL操作
UPDATE `user`
SET `sex` = '男'
-- 假设还有其他的操作也可以在这里添加
-- 如果一切正常,提交事务
COMMIT;
-- 如果出现错误或需要撤销更改,则回滚事务
-- ROLLBACK;
only_full_group_by
MySQL 中的一个 SQL 模式,判断sql的group是否正确,如果打开了这个严格模式,那么group中必须包含除了非聚合函数外所有select中的列,如果不包含,就会报错。如果关闭了,group就不会做校验
- 查询是否打开
--- 查询当前会话
SELECT @@GLOBAL.sql_mode;
--- 查询全局配置
SELECT @@SESSION.sql_mode;
- 打开
--- 当前会话
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY';
--- 全局
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY';
- 关闭
就是把上面的打开中的ONLY_FULL_GROUP_BY删掉执行一遍就好。 - 测试
- sql
SELECT call_type, id FROM oc_wyc_order GROUP BY call_type; - 打开的效果
打开了严格模式,如果没包含所有非聚合函数的值,就会报错

- 关闭的效果

- sql
本文介绍MySQL中的高级查询技巧,如GROUP_CONCAT函数的多种用法、JSON数据查询及处理,以及如何排查和解决死锁问题,包括查看未提交事务的状态和通过日志定位问题。

2555

被折叠的 条评论
为什么被折叠?



