SQL常用语句实战指南

作者:技术拾光

时间:2026-06-12

浏览:276

SQL是操作关系型数据库的标准语言,梳理了从入门到进阶的核心语句,涵盖增删改查、数据库架构与约束、多表关联等操作,覆盖日常开发90%以上场景,可作为新手教程和速查手册。

文章目录

SQL(Structured Query Language,结构化查询语言)是操作关系型数据库的标准语言,这一点恐怕没人有异议。不管是做数据查询、新增、修改、删除,还是搭数据库架构、管权限,都绕不开它。这篇文章把 SQL 从入门到进阶的核心语句梳理了一遍,日常开发 90% 以上的场景基本都能覆盖。可以把它当成新手的入门教程,也是老手随手翻的速查手册。

SQL常用语句实战指南

一、基础入门: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 排序字段;

三种关联方式说明

  1. INNER JOIN(内连接):只返回两张表中同时满足关联条件的数据(交集),最常用。
  2. LEFT JOIN(左连接):以左表(表 1)为基准,返回左表所有数据,右表匹配上的就返回,没匹配上的用 NULL 填充。
  3. 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;

五、总结与注意事项

  1. SQL 书写规范:关键字(SELECT、INSERT 等)建议大写,字段名、表名小写,增强可读性;缩进对齐,便于后期维护。
  2. 避免性能陷阱:尽量不使用 SELECT *,精准查询所需字段;避免在 WHERE 子句中对字段使用函数(会导致索引失效);大批量操作数据时,优先使用批量语句(如批量 INSERT)。
  3. 谨慎使用危险操作:UPDATE、DELETE、DROP、TRUNCATE 等语句,使用前务必加 WHERE 条件(除全表操作外),最好先备份数据或通过事务测试。
  4. 不同数据库差异:本文语法以 MySQL 为主,Oracle、SQL Server 等数据库在分页、函数等方面略有差异,使用时需针对性调整。

这份 SQL 语句大全涵盖了日常开发的核心场景,建议收藏备用。随着使用熟练度的提升,可以进一步学习索引优化、存储过程、视图等高级内容,把 SQL 玩得更溜。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章