SQL 语句从基础到高级

SQL(Structured Query Language,结构化查询语言)是关系型数据库的标准操作语言,适用于 MySQL、Oracle、SQL Server、PostgreSQL 等主流数据库。本文将由浅入深,从基础语法、核心操作、进阶查询到高级特性、实战优化,全方位覆盖 SQL 常用语句,附带可直接运行的实战案例,零基础也能快速掌握。

前置说明:本文案例通用 90% 数据库,少量差异化语法会单独标注;所有案例基于通用数据表(用户表、订单表、商品表)演示,贴合实际业务。

一、SQL 基础认知与通用规范

1.1 SQL 分类

日常开发中核心使用 4 大类语句,也是本文重点讲解内容:

  • DQL(数据查询语言) :核心SELECT,用于查询数据(使用频率最高)
  • DML(数据操作语言)INSERT/UPDATE/DELETE,用于增改删数据
  • DDL(数据定义语言)CREATE/ALTER/DROP,用于创建、修改、删除数据库、表、字段
  • DCL(数据控制语言)GRANT/REVOKE,用于权限管理

1.2 通用语法规范

  • SQL 语句不区分大小写,关键字建议大写(规范可读性)
  • 每条语句以分号; 结尾
  • 单行注释:-- 注释内容;多行注释:/* 注释内容 */
  • 字符串使用单引号 '内容',字段别名可使用双引号或反引号

二、SQL 基础操作

2.1 DDL 数据库与表操作

用于创建、修改、删除数据库和数据表,是建库建表的基础。

2.1.1 数据库操作

sql

复制代码
-- 1. 创建数据库(指定编码,避免中文乱码)
CREATE DATABASE IF NOT EXISTS test_db DEFAULT CHARACTER SET utf8mb4;

-- 2. 查看所有数据库
SHOW DATABASES;

-- 3. 使用/切换数据库
USE test_db;

-- 4. 查看当前数据库
SELECT DATABASE();

-- 5. 删除数据库
DROP DATABASE IF EXISTS test_db;

2.1.2 数据表操作

sql

复制代码
-- 1. 创建数据表(核心:字段名+数据类型+约束)
CREATE TABLE IF NOT EXISTS user (
    id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID,主键自增',
    username VARCHAR(50) NOT NULL COMMENT '用户名',
    age INT DEFAULT 18 COMMENT '年龄',
    gender CHAR(1) COMMENT '性别',
    create_time DATETIME DEFAULT NOW() COMMENT '创建时间',
    is_delete TINYINT DEFAULT 0 COMMENT '删除标记:0未删除,1已删除'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

-- 2. 查看当前库所有表
SHOW TABLES;

-- 3. 查看表结构
DESC user;

-- 4. 修改表结构
-- 新增字段
ALTER TABLE user ADD COLUMN phone VARCHAR(11) COMMENT '手机号';
-- 修改字段类型
ALTER TABLE user MODIFY COLUMN age TINYINT;
-- 删除字段
ALTER TABLE user DROP COLUMN phone;
-- 修改表名
ALTER TABLE user RENAME TO user_info;

-- 5. 删除数据表
DROP TABLE IF EXISTS user_info;

2.2 DML 数据增删改操作

针对表中数据的新增、修改、删除,日常业务高频操作。

2.2.1 新增数据 INSERT

sql

复制代码
-- 方式1:指定字段插入
INSERT INTO user(username, age, gender) VALUES ('张三', 22, '男');

-- 方式2:全字段插入(需和表字段顺序一致)
INSERT INTO user VALUES (NULL, '李四', 25, '女', NOW(), 0);

-- 方式3:批量插入(高效推荐)
INSERT INTO user(username, age, gender) 
VALUES 
('王五', 20, '男'),
('赵六', 23, '女');

2.2.2 修改数据 UPDATE

重要:修改必须加 WHERE 条件,否则更新全表!

sql

复制代码
-- 单字段修改
UPDATE user SET age = 24 WHERE username = '张三';

-- 多字段修改
UPDATE user SET age = 26, gender = '男' WHERE id = 2;

-- 批量修改(匹配多条条件数据)
UPDATE user SET create_time = NOW() WHERE age > 20;

2.2.3 删除数据 DELETE

重要:删除必须加 WHERE 条件,否则清空全表!

sql

复制代码
-- 条件删除单条/多条数据
DELETE FROM user WHERE id = 3;

-- 清空表数据(保留表结构,可回滚)
DELETE FROM user;

-- 快速清空表数据(不可回滚、自增主键重置,速度更快)
TRUNCATE TABLE user;

2.3 基础 DQL 查询语句

SELECT 查询是 SQL 重中之重,所有数据展示、统计、筛选都依赖此语句。

2.3.1 基础查询语法

sql

复制代码
-- 1. 查询所有字段
SELECT * FROM user;

-- 2. 查询指定字段(推荐,避免冗余字段)
SELECT id, username, age FROM user;

-- 3. 字段起别名 AS(可省略)
SELECT id AS 用户ID, username 用户名, age 年龄 FROM user;

-- 4. 去重查询 DISTINCT
SELECT DISTINCT age FROM user;

-- 5. 限制查询条数 LIMIT(分页核心)
SELECT * FROM user LIMIT 2; -- 查询前2条
SELECT * FROM user LIMIT 1,2; -- 从第2条开始,查询2条(分页公式:LIMIT (page-1)*size, size)

2.3.2 条件查询 WHERE

用于筛选符合条件的数据,支持多种运算符:比较、逻辑、模糊、范围等。

sql

复制代码
-- 比较运算符:=、!=、>、<、>=、<=
SELECT * FROM user WHERE age > 20;
SELECT * FROM user WHERE username != '张三';

-- 逻辑运算符:AND、OR、NOT
SELECT * FROM user WHERE age > 20 AND gender = '男';
SELECT * FROM user WHERE age < 18 OR age > 30;

-- 范围查询 BETWEEN ... AND ...
SELECT * FROM user WHERE age BETWEEN 20 AND 25;

-- 枚举查询 IN
SELECT * FROM user WHERE age IN (20,22,24);

-- 空值判断 IS NULL / IS NOT NULL
SELECT * FROM user WHERE phone IS NULL;
SELECT * FROM user WHERE phone IS NOT NULL;

2.3.3 模糊查询 LIKE

通配符:% 匹配任意多个字符,_ 匹配单个字符

sql

复制代码
-- 用户名包含"张"
SELECT * FROM user WHERE username LIKE '%张%';

-- 用户名以"李"开头
SELECT * FROM user LIKE '李%';

-- 用户名第二个字为"五"
SELECT * FROM user WHERE username LIKE '_五%';

2.3.4 排序查询 ORDER BY

ASC 升序(默认),DESC 降序

sql

复制代码
-- 年龄升序
SELECT * FROM user ORDER BY age ASC;

-- 年龄降序
SELECT * FROM user ORDER BY age DESC;

-- 多字段排序:年龄降序,同龄则ID升序
SELECT * FROM user ORDER BY age DESC, id ASC;

三、SQL 进阶核心操作

3.1 聚合函数与分组查询

聚合函数用于数据统计,分组查询用于分类统计,是报表、数据统计核心语法。

3.1.1 常用聚合函数

sql

复制代码
-- COUNT:统计条数
SELECT COUNT(*) 总人数 FROM user; -- 统计所有数据
SELECT COUNT(age) 有效年龄人数 FROM user; -- 忽略NULL值

-- MAX/MIN:最大/最小值
SELECT MAX(age) 最大年龄, MIN(age) 最小年龄 FROM user;

-- SUM:求和
SELECT SUM(age) 年龄总和 FROM user;

-- AVG:平均值
SELECT AVG(age) 平均年龄 FROM user;

3.1.2 分组查询 GROUP BY

语法规则:SELECT 后的非聚合字段,必须出现在GROUP BY 后;HAVING 用于分组后筛选(替代 WHERE,WHERE 不能用于分组后)

sql

复制代码
-- 按性别分组,统计每组人数
SELECT gender, COUNT(*) 人数 FROM user GROUP BY gender;

-- 按年龄分组,统计每组人数,筛选人数大于1的分组
SELECT age, COUNT(*) 人数 FROM user GROUP BY age HAVING 人数 > 1;

-- 多字段分组:按性别+年龄分组统计
SELECT gender, age, COUNT(*) 人数 FROM user GROUP BY gender, age;

3.2 多表联查

实际业务中数据分散在多张表,必须通过联查获取完整数据,核心 4 种连接方式。 演示表:用户表 user、订单表 order(user_id 关联用户 ID)

3.2.1 内连接 INNER JOIN

只查询两张表中匹配的数据,无匹配则不显示

sql

复制代码
-- 查询用户及对应的订单信息
SELECT u.username, o.order_id, o.order_price
FROM user u
INNER JOIN `order` o 
ON u.id = o.user_id;

3.2.2 左连接 LEFT JOIN

左表为基准,左表数据全部展示,右表无匹配则显示 NULL(业务最常用)

sql

复制代码
-- 查询所有用户,包含无订单的用户
SELECT u.username, o.order_id, o.order_price
FROM user u
LEFT JOIN `order` o 
ON u.id = o.user_id;

3.2.3 右连接 RIGHT JOIN

右表为基准,右表数据全部展示,左表无匹配则显示 NULL

sql

复制代码
-- 查询所有订单,包含无对应用户的订单数据
SELECT u.username, o.order_id, o.order_price
FROM user u
RIGHT JOIN `order` o 
ON u.id = o.user_id;

3.2.4 全连接 UNION

合并两张表所有数据,MySQL 无直接 FULL JOIN,通过 UNION 实现

sql

复制代码
SELECT u.username, o.order_id FROM user u LEFT JOIN `order` o ON u.id = o.user_id
UNION
SELECT u.username, o.order_id FROM user u RIGHT JOIN `order` o ON u.id = o.user_id;

3.3 子查询

将一条 SQL 查询结果作为另一条 SQL 的参数,分为单行子查询、多行子查询、嵌套子查询。

3.3.1 单行子查询

sql

复制代码
-- 查询年龄大于平均年龄的用户
SELECT * FROM user WHERE age > (SELECT AVG(age) FROM user);

3.3.2 多行子查询(IN/EXISTS)

sql

复制代码
-- IN:匹配子查询返回的任意值
SELECT * FROM user WHERE id IN (SELECT user_id FROM `order`);

-- EXISTS:判断子查询是否有结果(效率高于IN)
SELECT * FROM user u WHERE EXISTS (SELECT 1 FROM `order` o WHERE o.user_id = u.id);

3.3.3 派生表子查询(FROM 后子查询)

sql

复制代码
-- 先统计各年龄人数,再筛选人数大于1的记录
SELECT * FROM (SELECT age, COUNT(*) 人数 FROM user GROUP BY age) AS temp WHERE 人数 > 1;

四、SQL 高级特性

4.1 事务 Transaction

事务用于保证数据一致性,核心ACID 四大特性(原子性、一致性、隔离性、持久性),适用于转账、下单等多步数据操作场景。 MySQL InnoDB 引擎支持事务,MyISAM 不支持。

sql

复制代码
-- 1. 开启事务
START TRANSACTION;

-- 2. 执行多条数据操作
UPDATE user SET age = 23 WHERE id = 1;
UPDATE user SET age = 21 WHERE id = 2;

-- 3. 提交事务(数据永久生效)
COMMIT;

-- 回滚事务(取消所有操作,数据恢复原状)
ROLLBACK;

4.2 索引操作

索引是提升查询效率的核心,合理建索引可大幅优化 SQL 性能。

sql

复制代码
-- 1. 查看表索引
SHOW INDEX FROM user;

-- 2. 创建普通索引
CREATE INDEX idx_user_age ON user(age);

-- 3. 创建唯一索引(字段值唯一,允许NULL)
CREATE UNIQUE INDEX idx_user_phone ON user(phone);

-- 4. 创建联合索引
CREATE INDEX idx_user_age_gender ON user(age, gender);

-- 5. 删除索引
DROP INDEX idx_user_age ON user;

4.3 视图、存储过程、触发器

4.3.1 视图 VIEW

虚拟表,封装复杂查询语句,简化重复查询,不存储真实数据

sql

复制代码
-- 创建视图
CREATE VIEW v_user_order AS
SELECT u.username, o.order_id, o.order_price FROM user u LEFT JOIN `order` o ON u.id = o.user_id;

-- 使用视图(直接查询虚拟表)
SELECT * FROM v_user_order;

-- 删除视图
DROP VIEW IF EXISTS v_user_order;

4.3.2 存储过程 PROCEDURE

封装一段 SQL 逻辑,可重复调用,支持参数传递,适合复杂批量操作

sql

复制代码
-- 创建无参存储过程
DELIMITER // -- 修改语句结束符为//
CREATE PROCEDURE get_user_list()
BEGIN
    SELECT * FROM user WHERE is_delete = 0;
END //
DELIMITER ; -- 恢复默认结束符

-- 调用存储过程
CALL get_user_list();

-- 删除存储过程
DROP PROCEDURE IF EXISTS get_user_list;

4.3.3 触发器 TRIGGER

监听表的增删改操作,触发自动执行指定 SQL 逻辑

sql

复制代码
-- 创建触发器:新增用户后自动打印日志(简易示例)
DELIMITER //
CREATE TRIGGER trigger_user_add
AFTER INSERT ON user
FOR EACH ROW
BEGIN
    INSERT INTO log_table(content) VALUES (CONCAT('新增用户:', NEW.username));
END //
DELIMITER ;

-- 删除触发器
DROP TRIGGER IF EXISTS trigger_user_add;

4.4 窗口函数(SQL 高级查询)

窗口函数是数据分析、排名、分组统计的高级用法,不压缩行数(区别于 GROUP BY),MySQL8.0+、Oracle、SQL Server 支持。

4.4.1 排名函数

sql

复制代码
-- ROW_NUMBER():连续排名(1,2,3,4)
-- RANK():跳跃排名(1,2,2,4)
-- DENSE_RANK():密集排名(1,2,2,3)
SELECT 
    username,
    age,
    ROW_NUMBER() OVER(ORDER BY age DESC) 连续排名,
    RANK() OVER(ORDER BY age DESC) 跳跃排名,
    DENSE_RANK() OVER(ORDER BY age DESC) 密集排名
FROM user;

4.4.2 分区窗口函数

sql

复制代码
-- 按性别分区,统计各性别年龄排名
SELECT 
    username, gender, age,
    ROW_NUMBER() OVER(PARTITION BY gender ORDER BY age DESC) 性别内年龄排名
FROM user;

五、SQL 实战优化与避坑指南

5.1 高频错误避坑

  • 禁止全表更新 / 删除:UPDATE/DELETE 必须加 WHERE 条件,生产环境建议先 SELECT 验证条件
  • SELECT * 慎用:只查询业务需要的字段,减少 IO 消耗
  • GROUP BY 规范:非聚合字段必须分组,避免语法报错或数据错乱
  • 模糊查询前置 % 禁用:LIKE '% 张三 %'、LIKE '% 张三 ' 无法走索引,查询效率极低

5.2 SQL 性能优化核心

  • WHERE 条件优先过滤数据,减少后续统计、联查的数据量
  • 联查字段、WHERE 条件字段、排序字段合理建立索引
  • 大表分页避免 LIMIT 100000,10,使用主键偏移分页优化
  • 优先使用 EXISTS 替代 IN,大数据量下效率差距明显
  • 避免在索引字段上使用函数、运算,会导致索引失效

六、常用 SQL 语句速查表

汇总日常开发高频语句,快速查阅使用:

  1. 基础查询:SELECT 字段 FROM 表 WHERE 条件 LIMIT 条数
  2. 统计查询:SELECT 聚合函数 FROM 表 GROUP BY 字段 HAVING 条件
  3. 多表联查:JOIN 表 ON 关联条件 + 筛选条件
  4. 数据操作:INSERT/UPDATE/DELETE 配合 WHERE 精准操作
  5. 性能优化:索引优化、避免全表扫描、合理使用窗口函数 / 子查询
相关推荐
IvorySQL1 小时前
PG 日报|多款 PostgreSQL 工具新版本集中发布
数据库·postgresql
不剪发的Tony老师2 小时前
金仓数据库在线体验:简单易用
数据库·金仓数据库
techdashen2 小时前
Uber 的全局限流系统:从零散 Redis 限流到服务网格里的自动化流量保护
数据库·redis·自动化
白露与泡影2 小时前
慢 SQL 不一定是 SQL 慢:一次 MySQL 连接池耗尽的故障定位
数据库·sql·mysql
IT 小阿姨(数据库)2 小时前
PostgreSQL 因主库表空间错乱_缺少软链接、从库配置问题,导致主从复制故障【修复过程】
数据库·postgresql
爱敲代码的小鱼2 小时前
springsecurity:
java·开发语言·数据库
秋田君2 小时前
QT_QT信号与槽机制
开发语言·数据库·qt
DFT计算杂谈3 小时前
vasp如何计算金属的铁电极化强度?
数据库
EterNity_TiMe_3 小时前
别让告警变成噪音:用Prometheus和Alertmanager搭一套可远程查看的监控系统
数据库·人工智能·ai·postgresql·prometheus·cpolar