SQL是操作关系型数据库的标准语言,梳理了从入门到进阶的核心语句,涵盖增删改查、数据库架构与约束、多表关联等操作,覆盖日常开发90%以上场景,可作为新手教程和速查手册。
SQL常用语句实战指南
时间:2026-06-12
浏览:276
文章目录
SQL(Structured Query Language,结构化查询语言)是操作关系型数据库的标准语言,这一点恐怕没人有异议。不管是做数据查询、新增、修改、删除,还是搭数据库架构、管权限,都绕不开它。这篇文章把 SQL 从入门到进阶的核心语句梳理了一遍,日常开发 90% 以上的场景基本都能覆盖。可以把它当成新手的入门教程,也是老手随手翻的速查手册。

一、基础入门:SQL 核心四大操作(DML)
DML(Data Manipulation Language,数据操作语言)是平时用得最多的 SQL 子集,专门用来操作数据表中的数据。核心就四个字:增(INSERT)、查(SELECT)、改(UPDATE)、删(DELETE)。
1. 新增数据(INSERT)
往表里插数据,支持单条插、批量插,还能从别的表查出来再插进去。
语法 1:直接插入单条 / 多条数据
-- 单条数据插入(指定字段,推荐用法,字段顺序可与表结构不一致) INSERT INTO 表名 (字段1, 字段2, 字段3, ...) VALUES (值1, 值2, 值3, ...); -- 多条数据插入(MySQL 5.7+、PostgreSQL等支持,高效批量插入) INSERT INTO 表名 (字段1, 字段2, 字段3, ...) VALUES (值1-1, 值1-2, 值1-3, ...), (值2-1, 值2-2, 值2-3, ...), (值3-1, 值3-2, 值3-3, ...); -- 简化写法(不指定字段,必须与表结构字段顺序、数量完全一致,不推荐) INSERT INTO 表名 VALUES (值1, 值2, 值3, ...);
语法 2:从其他表查询结果插入数据
INSERT INTO 目标表名 (字段1, 字段2, ...) SELECT 字段1, 字段2, ... FROM 来源表名 WHERE 筛选条件;
实操示例
-- 向用户表(user)插入单条数据 INSERT INTO user (id, username, age, create_time) VALUES (1, 'zhangsan', 25, NOW()); -- 向用户表批量插入3条数据 INSERT INTO user (id, username, age, create_time) VALUES (2, 'lisi', 28, NOW()), (3, 'wangwu', 30, NOW()), (4, 'zhaoliu', 22, NOW()); -- 从临时用户表(temp_user)查询年龄大于25的用户,插入到正式用户表 INSERT INTO user (id, username, age, create_time) SELECT id, username, age, create_time FROM temp_user WHERE age > 25;
2. 查询数据(SELECT)
查询是 SQL 里最核心的操作,没有之一。从简单查、条件查、排序、分页到聚合统计,花样很多。
语法 1:简单查询(查询全部 / 指定字段)
-- 查询表中所有字段的数据(* 代表全部字段,开发中不推荐,效率低且易出问题) SELECT * FROM 表名; -- 查询指定字段的数据(推荐用法,精准获取所需字段) SELECT 字段1, 字段2, ... FROM 表名; -- 查询时给字段起别名(AS 可省略,用于简化结果展示或避免字段名冲突) SELECT 字段1 AS 别名1, 字段2 别名2, ... FROM 表名; -- 查询去重数据(DISTINCT,去除结果集中重复的记录) SELECT DISTINCT 字段1, 字段2, ... FROM 表名;
语法 2:条件查询(WHERE)
通过 WHERE 子句加条件,只把满足条件的行捞出来。支持的运算符挺多,看下面这张表就清楚了。
SELECT 字段1, 字段2, ... FROM 表名 WHERE 筛选条件;
常用筛选运算符
| 运算符类型 | 具体运算符 | 说明 |
|---|---|---|
| 比较运算符 | =、>、<、>=、<=、<>(!=) | 等于、大于、小于、大于等于、小于等于、不等于 |
| 逻辑运算符 | AND、OR、NOT | 并且、或者、非 |
| 范围运算符 | BETWEEN ... AND ... | 在某个数值 / 日期范围内 |
| 集合运算符 | IN、NOT IN | 在 / 不在指定集合中 |
| 模糊运算符 | LIKE、NOT LIKE | 模糊匹配,% 匹配任意字符,_ 匹配单个字符 |
| 空值判断 | IS NULL、IS NOT NULL | 判断字段是否为 NULL(注意:不能用 = NULL) |
语法 3:排序(ORDER BY)
用 ORDER BY 控制结果集的排序方式,默认升序(ASC),也可以指定降序(DESC)。支持多字段排序,先按第一个排,再按第二个排。
SELECT 字段1, 字段2, ... FROM 表名 WHERE 筛选条件 ORDER BY 字段1 ASC/DESC, 字段2 ASC/DESC, ...;
语法 4:分页查询(LIMIT/ROWNUM/Top)
限制返回的行数,实现翻页。不同数据库的写法有点区别。
-- MySQL / PostgreSQL 用法(LIMIT 偏移量, 每页条数;偏移量从0开始) SELECT 字段1, 字段2, ... FROM 表名 WHERE 筛选条件 ORDER BY 字段1 DESC LIMIT 0, 10; -- 查询第1页,每页10条数据(偏移量0) -- Oracle 用法(ROWNUM) SELECT 字段1, 字段2, ... FROM 表名 WHERE 筛选条件 AND ROWNUM <= 10; -- SQL Server 用法(TOP) SELECT TOP 10 字段1, 字段2, ... FROM 表名 WHERE 筛选条件 ORDER BY 字段1 DESC;
语法 5:聚合查询(聚合函数)
做统计用:COUNT() 数条数,SUM() 求和,A VG() 求平均,MAX() 和 MIN() 取最大最小值。
SELECT COUNT(*) AS 总条数, SUM(字段1) AS 字段1总和, A VG(字段1) AS 字段1平均值, MAX(字段1) AS 字段1最大值, MIN(字段1) AS 字段1最小值 FROM 表名 WHERE 筛选条件;
语法 6:分组查询(GROUP BY + HA VING)
GROUP BY 按指定字段分组,每组返回一行统计结果。HA VING 用来过滤分组后的结果——注意它跟 WHERE 的区别:WHERE 过滤原始行,HA VING 过滤分组结果。
SELECT 分组字段, 聚合函数(字段) AS 别名 FROM 表名 WHERE 筛选原始数据的条件 GROUP BY 分组字段 HA VING 筛选分组结果的条件 ORDER BY 别名 DESC;
实操示例
-- 1. 查询用户表中所有年龄大于25的用户姓名和年龄 SELECT username, age FROM user WHERE age > 25; -- 2. 查询用户表中年龄在25到30之间的用户,按年龄降序排序 SELECT username, age FROM user WHERE age BETWEEN 25 AND 30 ORDER BY age DESC; -- 3. 查询用户表中姓“张”的用户(模糊匹配) SELECT username, age FROM user WHERE username LIKE '张%'; -- 4. 统计用户表中各年龄的用户数量,只显示用户数量大于1的年龄 SELECT age, COUNT(*) AS user_count FROM user GROUP BY age HA VING user_count > 1 ORDER BY user_count DESC; -- 5. 查询用户表第2页数据,每页10条(MySQL) SELECT username, age, create_time FROM user ORDER BY create_time DESC LIMIT 10, 10;
3. 修改数据(UPDATE)
改数据一定要带 WHERE 条件,除非你真是想改全表。否则一不留神就把整个表的数据全改了,哭都来不及。
语法
UPDATE 表名 SET 字段1 = 新值1, 字段2 = 新值2, ... WHERE 筛选条件; -- 关键:限定修改范围,避免误操作
实操示例
-- 1. 修改用户表中id=1的用户年龄为26 UPDATE user SET age = 26 WHERE id = 1; -- 2. 修改用户表中姓“李”的用户年龄加1,创建时间更新为当前时间 UPDATE user SET age = age + 1, create_time = NOW() WHERE username LIKE '李%';
4. 删除数据(DELETE)
删除和修改一样,WHERE 条件必须写清楚,不然就是删全表。删除全表有两种方式:DELETE 逐行删,可以回滚;TRUNCATE 直接清空,效率高但不可回滚,还会重置自增 ID。
语法 1:删除指定条件的数据
DELETE FROM 表名 WHERE 筛选条件;
语法 2:删除全表数据(两种方式)
-- 方式1:DELETE(逐行删除,支持事务,可回滚,效率较低) DELETE FROM 表名; -- 方式2:TRUNCATE(清空全表,不支持事务,不可回滚,效率极高,会重置自增字段) TRUNCATE TABLE 表名;
实操示例
-- 1. 删除用户表中id=4的用户 DELETE FROM user WHERE id = 4; -- 2. 删除用户表中年龄小于20的用户 DELETE FROM user WHERE age < 20; -- 3. 清空用户表(不可回滚,谨慎使用) TRUNCATE TABLE user;
二、核心进阶:数据库架构与约束(DDL)
DDL(Data Definition Language)用来定义数据库的结构——建库、建表、改表、删表,还有加各种约束,是搭架子用的。
1. 数据库操作(CREATE/DROP/USE)
-- 1. 创建数据库(指定字符集,避免中文乱码) CREATE DATABASE IF NOT EXISTS 数据库名 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 2. 删除数据库(谨慎使用,删除后所有数据丢失) DROP DATABASE IF EXISTS 数据库名; -- 3. 切换数据库(后续操作针对该数据库) USE 数据库名;
2. 数据表操作(CREATE/ALTER/DROP)
语法 1:创建数据表(CREATE TABLE)
CREATE TABLE IF NOT EXISTS 表名 ( 字段1 数据类型 约束条件, 字段2 数据类型 约束条件, 字段3 数据类型 约束条件, ..., 额外约束(如主键约束、唯一约束) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
常用数据类型
| 数据类型 | 说明 | 示例 |
|---|---|---|
| INT | 整数类型(可指定长度,支持自增) | INT(11)、INT AUTO_INCREMENT |
| VARCHAR(n) | 可变长度字符串(n 为最大长度,1-65535) | VARCHAR(50)(最多存 50 个字符) |
| CHAR(n) | 固定长度字符串(n 为固定长度,1-255) | CHAR(10)(无论存多少,都占 10 个字符) |
| DATETIME | 日期时间类型(格式:YYYY-MM-DD HH:MM:SS) | DATETIME |
| DATE | 日期类型(格式:YYYY-MM-DD) | DATE |
| DECIMAL(m,n) | 高精度小数(m 为总长度,n 为小数位数) | DECIMAL(10,2)(最大 10 位数字,2 位小数) |
常用约束条件
| 约束 | 说明 | 语法 |
|---|---|---|
| PRIMARY KEY | 主键约束(唯一标识一条记录,非空且唯一) | PRIMARY KEY |
| AUTO_INCREMENT | 自增约束(仅用于整数类型,配合主键使用) | AUTO_INCREMENT |
| NOT NULL | 非空约束(字段值不能为 NULL) | NOT NULL |
| UNIQUE | 唯一约束(字段值唯一,可多个 NULL) | UNIQUE |
| DEFAULT | 默认值约束(字段未赋值时使用默认值) | DEFAULT 0 / DEFAULT NOW() |
| FOREIGN KEY | 外键约束(关联另一张表的主键,保证数据一致性) | FOREIGN KEY (字段) REFERENCES 关联表 (关联字段) |
语法 2:修改数据表(ALTER TABLE)
改表名、加字段、改字段、删字段、加约束、删约束,都能用 ALTER TABLE 搞定。
-- 1. 修改表名 ALTER TABLE 旧表名 RENAME TO 新表名; -- 2. 添加字段 ALTER TABLE 表名 ADD 字段名 数据类型 约束条件 [AFTER 已有字段]; -- 3. 修改字段(修改数据类型、约束) ALTER TABLE 表名 MODIFY 字段名 新数据类型 新约束条件; -- 4. 重命名字段 ALTER TABLE 表名 CHANGE 旧字段名 新字段名 数据类型 约束条件; -- 5. 删除字段 ALTER TABLE 表名 DROP 字段名; -- 6. 添加主键约束 ALTER TABLE 表名 ADD PRIMARY KEY (字段名); -- 7. 删除主键约束 ALTER TABLE 表名 DROP PRIMARY KEY;
语法 3:删除数据表(DROP TABLE)
-- 删除数据表(谨慎使用,删除后表结构和数据全部丢失) DROP TABLE IF EXISTS 表名;
实操示例
-- 1. 创建用户表(包含主键、自增、非空、默认值约束) CREATE TABLE IF NOT EXISTS user ( id INT(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID(主键)', username VARCHAR(50) NOT NULL COMMENT '用户名', age INT(3) DEFAULT 0 COMMENT '用户年龄', email VARCHAR(100) UNIQUE COMMENT '用户邮箱(唯一)', create_time DATETIME DEFAULT NOW() COMMENT '创建时间', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT '用户信息表'; -- 2. 给用户表添加“性别”字段 ALTER TABLE user ADD gender TINYINT(1) DEFAULT 0 COMMENT '性别(0:未知,1:男,2:女)' AFTER age; -- 3. 修改用户表中“email”字段的长度为150 ALTER TABLE user MODIFY email VARCHAR(150) UNIQUE COMMENT '用户邮箱(唯一)'; -- 4. 删除用户表中的“gender”字段 ALTER TABLE user DROP gender; -- 5. 删除用户表 DROP TABLE IF EXISTS user;
三、高级技巧:多表关联与子查询
实际开发中单表查询根本不够用,多张表一关联,或者嵌套个子查询,才能拿到想要的数据。
1. 多表关联查询(JOIN)
通过共同字段把多张表串起来。最常用的三种:INNER JOIN(内连接)、LEFT JOIN(左连接)、RIGHT JOIN(右连接)。
核心语法
SELECT 表1.字段1, 表2.字段2, ... FROM 表1 [INNER/LEFT/RIGHT] JOIN 表2 ON 表1.关联字段 = 表2.关联字段 -- 关键:指定关联条件 WHERE 额外筛选条件 ORDER BY 排序字段;
三种关联方式说明
- INNER JOIN(内连接):只返回两张表中同时满足关联条件的数据(交集),最常用。
- LEFT JOIN(左连接):以左表(表 1)为基准,返回左表所有数据,右表匹配上的就返回,没匹配上的用 NULL 填充。
- RIGHT JOIN(右连接):以右表(表 2)为基准,返回右表所有数据,左表匹配上的就返回,没匹配上的用 NULL 填充。
实操示例
-- 先创建两张关联表:用户表(user)、订单表(order)(订单表中的user_id关联用户表的id) CREATE TABLE IF NOT EXISTS user ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, age INT(3) DEFAULT 0 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS `order` ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, order_no VARCHAR(30) NOT NULL UNIQUE, user_id INT(11) NOT NULL, amount DECIMAL(10,2) NOT NULL, create_time DATETIME DEFAULT NOW(), FOREIGN KEY (user_id) REFERENCES user(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 1. 内连接:查询有订单记录的用户姓名和对应的订单号、金额 SELECT u.username, o.order_no, o.amount FROM user u -- 给表起别名,简化代码 INNER JOIN `order` o ON u.id = o.user_id ORDER BY o.create_time DESC; -- 2. 左连接:查询所有用户的姓名,以及对应的订单号(无订单的用户也会显示,订单字段为NULL) SELECT u.username, o.order_no, o.amount FROM user u LEFT JOIN `order` o ON u.id = o.user_id ORDER BY u.id ASC;
2. 子查询
把一个查询的结果拿来做另一个查询的条件、数据源或者字段值。分三类:标量子查询(返回单个值)、列子查询(返回一列)、表子查询(返回一张临时表)。
语法 1:标量子查询(返回单个值,用于 =、>、< 等比较运算符)
-- 查询订单金额最高的订单信息 SELECT * FROM `order` WHERE amount = (SELECT MAX(amount) FROM `order`);
语法 2:列子查询(返回一列数据,用于 IN、NOT IN、EXISTS 等运算符)
-- 查询有订单记录的所有用户信息 SELECT * FROM user WHERE id IN (SELECT DISTINCT user_id FROM `order`);
语法 3:表子查询(返回一张临时表,用于 FROM 子句)
-- 统计每个用户的订单总金额,显示用户名和总金额 SELECT u.username, t.total_amount FROM user u LEFT JOIN ( SELECT user_id, SUM(amount) AS total_amount FROM `order` GROUP BY user_id ) t -- 子查询返回临时表t ON u.id = t.user_id ORDER BY t.total_amount DESC;
四、实用补充:事务与权限管理
1. 事务操作(TRANSACTION)
事务就是一组要么全成功要么全失败的 SQL 操作,保证数据的一致性。最经典的场景就是转账——扣钱和加钱必须同时成功或同时失败。
核心语法
-- 开启事务 START TRANSACTION; -- 或 BEGIN; -- 执行一系列SQL操作(INSERT、UPDATE、DELETE等) UPDATE account SET balance = balance - 100 WHERE id = 1; UPDATE account SET balance = balance + 100 WHERE id = 2; -- 提交事务(所有操作执行成功,持久化到数据库) COMMIT; -- 回滚事务(发生错误,撤销所有已执行的操作,恢复到事务开启前的状态) ROLLBACK;
2. 权限管理(GRANT/REVOKE)
给用户分配或回收权限,保证数据库安全。常用的权限有 SELECT、INSERT、UPDATE、DELETE、ALL PRIVILEGES。
核心语法
-- 1. 创建用户(用户名@主机地址,密码为123456) CREATE USER 'username'@'localhost' IDENTIFIED BY '123456'; -- 2. 分配权限(给用户分配某个数据库的查询、新增权限) GRANT SELECT, INSERT ON 数据库名.* TO 'username'@'localhost'; -- 3. 回收权限(回收用户的新增权限) REVOKE INSERT ON 数据库名.* FROM 'username'@'localhost'; -- 4. 刷新权限(使权限变更生效) FLUSH PRIVILEGES;
五、总结与注意事项
- SQL 书写规范:关键字(SELECT、INSERT 等)建议大写,字段名、表名小写,增强可读性;缩进对齐,便于后期维护。
- 避免性能陷阱:尽量不使用
SELECT *,精准查询所需字段;避免在 WHERE 子句中对字段使用函数(会导致索引失效);大批量操作数据时,优先使用批量语句(如批量 INSERT)。 - 谨慎使用危险操作:UPDATE、DELETE、DROP、TRUNCATE 等语句,使用前务必加 WHERE 条件(除全表操作外),最好先备份数据或通过事务测试。
- 不同数据库差异:本文语法以 MySQL 为主,Oracle、SQL Server 等数据库在分页、函数等方面略有差异,使用时需针对性调整。
这份 SQL 语句大全涵盖了日常开发的核心场景,建议收藏备用。随着使用熟练度的提升,可以进一步学习索引优化、存储过程、视图等高级内容,把 SQL 玩得更溜。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。