SQL常用语句大全!!!(语法+实战)
SQL(Structured Query Language,结构化查询语言)是操作关系型数据库的标准语言,无论是数据查询、新增、修改、删除,还是数据库架构设计、权限管理,都离不开 SQL。本文整理了 SQL 从入门到进阶的核心语句,涵盖日常开发 90% 以上的使用场景,既是新手入门的教程,也是资深开发者的实用速查手册。
一、基础入门:SQL 核心四大操作(DML)
DML(Data Manipulation Language,数据操作语言)是最常用的 SQL 子集,主要用于操作数据表中的数据,核心包含查询(SELECT)、新增(INSERT)、修改(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, ...; -- 支持多字段排序,先按字段1排,再按字段2排 语法 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()(求和)、AVG()(平均值)、MAX()(最大值)、MIN()(最小值)。
SELECT COUNT(*) AS 总条数, SUM(字段1) AS 字段1总和, AVG(字段1) AS 字段1平均值, MAX(字段1) AS 字段1最大值, MIN(字段1) AS 字段1最小值 FROM 表名 WHERE 筛选条件; 语法 6:分组查询(GROUP BY + HAVING)
GROUP BY 用于将数据按指定字段分组,每组返回一条统计结果;HAVING 用于对分组后的结果进行筛选(区别于 WHERE:WHERE 筛选原始数据,HAVING 筛选分组结果)。
SELECT 分组字段, 聚合函数(字段) AS 别名 FROM 表名 WHERE 筛选原始数据的条件 GROUP BY 分组字段 HAVING 筛选分组结果的条件 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 HAVING 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 条件(除非要删除全表),否则会误删全表数据,且删除后难以恢复。
语法 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)
用于修改表名、添加 / 删除 / 修改字段、添加 / 删除约束。
-- 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)为基准,返回左表所有数据,右表(表 2)满足关联条件的数据匹配返回,不满足的返回 NULL。
- RIGHT JOIN(右连接):以右表(表 2)为基准,返回右表所有数据,左表(表 1)满足关联条件的数据匹配返回,不满足的返回 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 编写效率和性能。