一、SQL CRUD 核心概念:数据操作的四大基石
SQL(Structured Query Language)的核心价值在于高效操作关系型数据库,而 CRUD 是数据操作的四大核心场景,覆盖了从数据新增、查询、更新到删除的全生命周期:
-
C(Create) :新增数据,通过
INSERT语句向表中插入一条或多条记录; -
R(Read) :查询数据,通过
SELECT语句从表中筛选、提取所需数据(最常用场景); -
U(Update) :更新数据,通过
UPDATE语句修改表中已存在的记录; -
D(Delete) :删除数据,通过
DELETE语句移除表中不需要的记录。
前提说明:本文所有示例基于
MySQL 8.0
使用统一测试表
user_info,表结构如下:
-- 创建测试表(含主键、索引、约束示例)
CREATE TABLE user_info (
id INT PRIMARY KEY AUTO_INCREMENT, -- 主键自增
username VARCHAR(50) NOT NULL UNIQUE, -- 用户名(非空+唯一)
age TINYINT CHECK (age > 0 AND age 120), -- 年龄(范围约束)
gender ENUM('male', 'female', 'other'), -- 性别(枚举类型)
email VARCHAR(100) NOT NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间(默认当前时间)
update_time DATETIME ON UPDATE CURRENT_TIMESTAMP -- 更新时间(自动更新)
);
二、R(Read):查询数据 ------SQL 最核心的操作
SELECT 是 SQL 中使用频率最高的语句,支持简单查询、条件筛选、排序、分组、联表等复杂场景,核心语法:
SELECT [DISTINCT] 列名1, 列名2, ... -- DISTINCT:去重
FROM 表名
[WHERE 条件] -- 筛选行
[GROUP BY 列名] -- 分组(常与聚合函数配合)
[HAVING 分组条件] -- 筛选分组结果(区别于 WHERE:HAVING 后可接聚合函数)
[ORDER BY 列名 [ASC/DESC]] -- 排序(ASC升序,默认;DESC降序)
[LIMIT 偏移量, 条数]; -- 限制返回结果(分页常用)
1. 基础查询:查询所有 / 指定列
-- 1. 查询所有列(不推荐生产环境,性能差)
SELECT * FROM user_info;
-- 2. 查询指定列(推荐:只查需要的列)
SELECT username, age, email FROM user_info;
-- 3. 去重查询(例如:查询所有不重复的性别)
SELECT DISTINCT gender FROM user_info;
2. 条件查询:WHERE 子句(支持多条件组合)
| 运算符 | 说明 | 示例 |
|---|---|---|
= |
等于 | age = 25 |
!= |
不等于 | gender != 'male' |
>/</>= |
大小 | age >= 18 |
BETWEEN ... AND ... |
范围匹配 | age BETWEEN 20 AND 30(含 20 和 30) |
IN (...) |
多值匹配 | gender IN ('male', 'female') |
LIKE |
模糊匹配(%匹配任意字符,_匹配单个字符) |
username LIKE '张%'(姓张的用户) |
IS NULL/IS NOT NULL |
空值判断 | email IS NOT NULL |
AND/OR/NOT |
逻辑运算符 | age >= 18 AND gender = 'female' |
示例:查询 18-30 岁、性别为女性且邮箱不为空的用户,按年龄降序排列
SELECT username, age, email
FROM user_info
WHERE age BETWEEN 18 AND 30
AND gender = 'female'
AND email IS NOT NULL
ORDER BY age DESC;
3. 聚合查询与分组:GROUP BY + 聚合函数
常用聚合函数:COUNT()(计数)、SUM()(求和)、AVG()(平均值)、MAX()(最大值)、MIN()(最小值)
示例:按性别分组,统计各性别的用户数和平均年龄
SELECT
gender,
COUNT(id) AS user_count, -- AS:给列起别名
AVG(age) AS avg_age
FROM user_info
GROUP BY gender
HAVING user_count > 1; -- 筛选出用户数大于1的性别分组
注意:
HAVING与
WHERE的区别:
WHERE筛选原始数据,
HAVING筛选分组后的结果,且
HAVING可使用聚合函数。
4. 分页查询:LIMIT 子句(避免一次性查询大量数据)
-- 分页公式:LIMIT (页码-1)*每页条数, 每页条数
-- 示例:查询第2页数据,每页10条(页码从1开始)
SELECT username, age, create_time
FROM user_info
ORDER BY create_time DESC
LIMIT 10, 10; -- 偏移量10(跳过前10条),返回10条
SQL Server 用
TOP,PostgreSQL 用
LIMIT/OFFSET,语法略有差异,但核心逻辑一致。
三、C(Create):新增数据 ------ 向表中插入记录
INSERT 支持插入单条记录或多条记录,核心语法:
-- 方式1:指定列插入(推荐:顺序可自定义,不依赖表结构)
INSERT INTO 表名 (列名1, 列名2, ...)
VALUES (值1, 值2, ...);
-- 方式2:插入所有列(不推荐:依赖表结构顺序,易出错)
INSERT INTO 表名
VALUES (值1, 值2, ...); -- 值的顺序必须与表结构一致
-- 方式3:批量插入(高效:减少IO开销)
INSERT INTO 表名 (列名1, 列名2, ...)
VALUES (值1-1, 值1-2, ...),
(值2-1, 值2-2, ...),
(值3-1, 值3-2, ...);
实战示例
-- 1. 单条插入(指定列,忽略自增主键和默认值列)
INSERT INTO user_info (username, age, gender, email)
VALUES ('zhangsan', 25, 'male', 'zhangsan@example.com');
-- 2. 批量插入(推荐:一次插入3条记录)
INSERT INTO user_info (username, age, gender, email)
VALUES
('lisi', 28, 'female', 'lisi@example.com'),
('wangwu', 30, 'male', 'wangwu@example.com'),
('zhaoliu', 22, 'other', 'zhaoliu@example.com');
-- 3. 插入默认值(利用表中 DEFAULT 约束)
INSERT INTO user_info (username, age, gender, email)
VALUES ('qianqi', 24, 'female', DEFAULT); -- email 用默认值(若表中设置了DEFAULT)
注意:插入的值必须满足表约束(如
NOT NULL列必须传值,
UNIQUE列不能重复,
CHECK列需符合范围),否则会报错。
四、U(Update):更新数据 ------ 修改已有记录
UPDATE 用于修改表中已存在的记录,必须配合 WHERE 子句(否则会更新全表!),核心语法:
UPDATE 表名
SET 列名1 = 新值1, 列名2 = 新值2, ...
[WHERE 条件]; -- 关键:筛选需要更新的行
[LIMIT 条数]; -- 限制更新条数(MySQL特有,避免误操作)
实战示例
-- 1. 单条更新(修改指定用户的年龄和邮箱)
UPDATE user_info
SET age = 26, email = 'zhangsan_update@example.com'
WHERE username = 'zhangsan'; -- 用唯一标识(如username/主键)筛选,避免多更
-- 2. 批量更新(修改所有25岁以下用户的性别为'other')
UPDATE user_info
SET gender = 'other'
WHERE age -- 3. 安全更新(加 LIMIT,防止误写 WHERE 条件导致全表更新)
UPDATE user_info
SET email = 'test@example.com'
WHERE gender = 'male'
LIMIT 10; -- 最多更新10条
高危提醒:生产环境中,
UPDATE语句必须先写
WHERE条件并测试,建议开启数据库的 "安全更新模式"(如 MySQL 的
sql_safe_updates = 1),禁止无
WHERE的更新。
五、D(Delete):删除数据 ------ 移除不需要的记录
DELETE 用于删除表中的记录,同样必须配合 WHERE 子句(否则会删除全表!),核心语法:
DELETE FROM 表名
[WHERE 条件]; -- 筛选需要删除的行
[LIMIT 条数]; -- 限制删除条数(MySQL特有)
实战示例
-- 1. 单条删除(删除指定用户名的记录)
DELETE FROM user_info
WHERE username = 'zhaoliu';
-- 2. 批量删除(删除30岁以上的男性用户)
DELETE FROM user_info
WHERE age > 30 AND gender = 'male';
-- 3. 安全删除(加 LIMIT,防止误删全表)
DELETE FROM user_info
WHERE create_time 024-01-01'
LIMIT 5; -- 最多删除5条
-- 4. 清空表(慎用!)
TRUNCATE TABLE user_info; -- 等价于 DELETE FROM user_info,但效率更高(直接清空表,不记录日志)
关键区别:
DELETEvs
TRUNCATE
-
DELETE:逐条删除记录,支持WHERE筛选,会记录事务日志(可回滚),自增主键不会重置; -
TRUNCATE:直接清空表数据(保留表结构),不支持WHERE,不记录日志(不可回滚),自增主键会重置,效率远高于DELETE。
六、CRUD 实战:综合场景案例
需求:模拟用户管理系统的核心操作
-- 1. 新增3个测试用户
INSERT INTO user_info (username, age, gender, email)
VALUES
('user1', 19, 'male', 'user1@test.com'),
('user2', 27, 'female', 'user2@test.com'),
('user3', 35, 'male', 'user3@test.com');
-- 2. 查询所有20-30岁的用户,按创建时间降序排列
SELECT id, username, age, email, create_time
FROM user_info
WHERE age BETWEEN 20 AND 30
ORDER BY create_time DESC;
-- 3. 将user2的年龄更新为28,邮箱改为user2_update@test.com
UPDATE user_info
SET age = 28, email = 'user2_update@test.com'
WHERE username = 'user2';
-- 4. 删除年龄大于30的用户
DELETE FROM user_info
WHERE age > 30;
-- 5. 统计剩余用户的性别分布
SELECT gender, COUNT(id) AS user_count
FROM user_info
GROUP BY gender;
七、CRUD 核心注意事项与最佳实践
1. 性能优化
-
查询:避免
SELECT *,只查需要的列;给查询条件列加索引(如username、age);分页用LIMIT减少返回数据; -
新增:批量插入优先用
INSERT ... VALUES (...)批量语法,减少 SQL 执行次数; -
更新 / 删除:用唯一标识(主键、唯一索引列)作为
WHERE条件,避免全表扫描;
2. 数据安全
-
禁止无
WHERE的UPDATE/DELETE,开启数据库安全模式; -
生产环境中,执行
UPDATE/DELETE前先执行SELECT验证条件是否正确; -
敏感操作(如清空表、删除大量数据)需走审批流程,备份数据后再执行;
3. 兼容性问题
-
分页语法:MySQL 用
LIMIT,SQL Server 用TOP,PostgreSQL 用LIMIT/OFFSET; -
日期函数:MySQL 用
DATE_FORMAT(),SQL Server 用FORMAT(),需根据数据库调整; -
自增主键:MySQL 用
AUTO_INCREMENT,PostgreSQL 用SERIAL/IDENTITY。
参考资料:MySQL 8.0 官方文档(
https://dev.mysql.com/doc/refman/8.0/en/sql-statements.html
)