mysql语句大全

 人参与 | 时间:2026-10-17 07:26:45

MySQL这玩意儿,学起来容易,用起来全是坑。我见过太多人写SQL,明明索引建了,查询还是慢得像蜗牛爬。问题往往出在语句本身——写法不对,数据库再优化也白搭。下面这些语句,是我这几年踩坑踩出来的,直接上干货。

建表时别偷懒

CREATE TABLE users ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, email VARCHAR(100) UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_name (name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

注意utf8mb4,别再用utf8了,emoji存不进去的。还有,INT后面加UNSIGNED,主键自增够用几辈子。索引别乱建,但WHERE后面经常出现的字段,老老实实加上。

查询:别动不动就SELECT *

我见过一个接口,查用户列表,SELECT * 拉了30个字段,实际前端只用id和name。流量不要钱?改成这样:

SELECT id, name FROM users WHERE status = 1 ORDER BY created_at DESC LIMIT 20;

LIMIT分页必须配合ORDER BY,否则顺序随机,翻页会重复。深分页用WHERE id > 上次最大id,别用LIMIT 100000, 20,那玩意儿能扫全表。

JOIN写不对,等于慢性自杀

左连接右连接,很多人凭感觉写。记住:A LEFT JOIN B,以A为主,B没匹配的补NULL。反过来就是B为主。看个例子:

SELECT u.name, o.order_no FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE o.status = 'paid';

这里WHERE条件放在ON后面和WHERE后面,结果完全不同。放ON里,左表全保留;放WHERE里,相当于过滤掉了NULL,变成内连接。这个坑我踩过,查出来的数据少了一半,排查了一下午。

UPDATE和DELETE,手别抖

UPDATE users SET name = '张三' WHERE id = 100; DELETE FROM users WHERE id = 100;

没WHERE就是全表更新/删除,线上环境这么干,等着跑路吧。执行前先SELECT一下,确认条件对不对。还有,UPDATE记得加LIMIT 1,防止误伤。

聚合查询,HAVING别和WHERE搞混

WHERE在分组前过滤,HAVING在分组后过滤。比如查每个用户的订单总额大于1000的:

SELECT user_id, SUM(amount) AS total FROM orders WHERE status = 'paid' GROUP BY user_id HAVING total > 1000;

WHERE里不能用聚合函数,HAVING里可以。顺序是WHERE → GROUP BY → HAVING → ORDER BY。

子查询能少用就少用

IN子查询在MySQL 5.7里性能很差,会先查子查询再查外层。改成JOIN:

-- 慢 SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 100); -- 快 SELECT u.* FROM users u JOIN orders o ON u.id = o.user_id WHERE o.amount > 100;

EXISTS和IN也有讲究,外表小用IN,内表小用EXISTS。别问为什么,记结论就行。

索引失效的几种写法

在索引列上做运算、用函数、类型隐式转换,索引全废。比如:

-- 索引失效 SELECT * FROM users WHERE YEAR(created_at) = 2024; -- 走索引 SELECT * FROM users WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01';

还有LIKE '%abc' 前置百分号,索引也用不上。字符串字段不加引号,MySQL会隐式转换,索引照样失效。

事务和锁,别乱用

START TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2; COMMIT;

InnoDB默认行锁,但WHERE没走索引就升级成表锁。所以更新条件一定要走索引。还有,事务别开太久,不然锁一堆行,别人全等着。

最后说个观察:很多人学SQL就背语法,但真正写起来,差一个空格、少个引号,结果天差地别。我建议把常用语句存成代码片段,用的时候直接套,比每次手写靠谱。数据库这东西,敬畏心要有,手速要慢。

顶: 9踩: 296