1. MySQL表的基本查询与CRUD操作详解
作为一名数据库开发工程师,我经常需要处理各种数据操作需求。今天我将分享MySQL中最基础也最重要的CRUD操作(Create, Retrieve, Update, Delete),这些是每个数据库使用者必须掌握的技能。本文将通过实际案例,带你深入理解这些操作的原理和使用技巧。
1.1 数据创建(Create)
1.1.1 基本插入语法
创建数据是数据库操作的第一步,MySQL提供了灵活的INSERT语句:
sql复制INSERT [INTO] table_name
[(column [, column] ...)]
VALUES (value_list) [, (value_list)] ...
先创建一个学生表作为示例:
sql复制CREATE TABLE students (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
sn INT NOT NULL UNIQUE COMMENT '学号',
name VARCHAR(20) NOT NULL,
qq VARCHAR(20)
);
全列插入是最简单的插入方式,不需要指定列名:
sql复制INSERT INTO students VALUES (100, 10000, '小一', NULL);
INSERT INTO students VALUES (101, 10001, '小二', '11111');
注意:全列插入必须为所有列提供值,包括NULL值
1.1.2 指定列插入
当只需要插入部分列时,可以明确指定列名:
sql复制INSERT INTO students (id, sn, name) VALUES
(102, 20001, '小三'),
(103, 20002, '小四');
这种方式的优势:
- 不需要为所有列提供值
- 自增列可以自动填充
- 未指定的列会自动设为NULL或默认值
1.1.3 主键冲突处理
当插入数据出现主键或唯一键冲突时,MySQL提供了两种解决方案:
方案一:ON DUPLICATE KEY UPDATE
sql复制INSERT INTO students VALUES (101,10001,'小二','22222')
ON DUPLICATE KEY UPDATE sn=10002, name='小二', qq=22222;
执行结果有三种可能:
- 0行影响:冲突数据的值与UPDATE值相同
- 1行影响:表中没有冲突数据,数据被插入
- 2行影响:表中有冲突数据,数据被更新
方案二:REPLACE
sql复制REPLACE INTO students (sn, name) VALUES(20001,'三号');
REPLACE的行为:
- 无冲突时直接插入
- 有冲突时先删除再插入
实际工作中,ON DUPLICATE KEY UPDATE更常用,因为它不会删除原记录,只是更新指定字段
1.2 数据查询(Retrieve)
1.2.1 基本查询语法
SELECT语句是SQL中最复杂的语句之一,基本语法如下:
sql复制SELECT
[DISTINCT] {* | {column [, column] ...}
[FROM table_name]
[WHERE ...]
[ORDER BY column [ASC | DESC], ...]
LIMIT ...
创建成绩表作为示例:
sql复制CREATE TABLE exam_result (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL COMMENT '同学姓名',
chinese float DEFAULT 0.0 COMMENT '语文成绩',
math float DEFAULT 0.0 COMMENT '数学成绩',
english float DEFAULT 0.0 COMMENT '英语成绩'
);
INSERT INTO exam_result (name, chinese, math, english) VALUES
('唐三藏', 67, 98, 56),
('孙悟空', 87, 78, 77),
('猪悟能', 88, 98, 90),
('曹孟德', 82, 84, 67),
('刘玄德', 55, 85, 45),
('孙权', 70, 73, 78),
('宋公明', 75, 65, 30);
1.2.2 查询类型
全列查询(慎用)
sql复制SELECT * FROM exam_result;
为什么不建议使用全列查询?
- 查询的列越多,传输数据量越大
- 可能影响索引使用效率
指定列查询
sql复制SELECT name, math FROM exam_result;
表达式查询
sql复制SELECT name, chinese + math + english FROM exam_result;
别名查询
sql复制SELECT name, chinese+math+english AS total FROM exam_result;
-- 或省略AS
SELECT name 姓名, chinese+math+english 总分 FROM exam_result;
去重查询
sql复制SELECT DISTINCT math FROM exam_result;
1.2.3 WHERE条件查询
WHERE子句用于过滤记录,支持多种运算符:
| 运算符 | 说明 |
|---|---|
| >, >=, <, <= | 比较运算符 |
| = | 等于(NULL不安全) |
| <=> | 等于(NULL安全) |
| !=, <> | 不等于 |
| BETWEEN a0 AND a1 | 范围匹配 |
| IN (option,...) | 多值匹配 |
| IS NULL | 是NULL |
| IS NOT NULL | 不是NULL |
| LIKE | 模糊匹配 |
查询示例:
英语不及格的同学:
sql复制SELECT name, english FROM exam_result WHERE english < 60;
语文成绩在[80,90]分的同学:
sql复制-- 使用AND
SELECT name, chinese FROM exam_result
WHERE chinese >= 80 AND chinese <= 90;
-- 使用BETWEEN
SELECT name, chinese FROM exam_result
WHERE chinese BETWEEN 80 AND 90;
姓孙的同学:
sql复制-- %匹配任意多个字符
SELECT name FROM exam_result WHERE name LIKE '孙%';
-- _匹配单个字符
SELECT name FROM exam_result WHERE name LIKE '孙_';
1.2.4 结果排序
使用ORDER BY对结果排序:
sql复制-- 数学成绩升序(默认)
SELECT name, math FROM exam_result ORDER BY math;
-- 数学成绩降序
SELECT name, math FROM exam_result ORDER BY math DESC;
多字段排序(类似字典序):
sql复制SELECT name, math, english FROM exam_result
ORDER BY math DESC, english ASC, chinese ASC;
1.2.5 分页查询
LIMIT用于分页查询:
sql复制-- 从第0条开始,查询3条
SELECT * FROM exam_result LIMIT 3;
-- 从第1条开始,查询4条
SELECT * FROM exam_result LIMIT 1,4;
-- 等价于
SELECT * FROM exam_result LIMIT 4 OFFSET 1;
提示:对未知表查询时,建议加LIMIT 1,避免全表扫描导致性能问题
1.3 数据更新(Update)
UPDATE语句用于修改现有数据:
sql复制UPDATE table_name SET column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]
更新示例:
修改孙悟空数学成绩:
sql复制UPDATE exam_result SET math = 80 WHERE name = '孙悟空';
同时修改多个字段:
sql复制UPDATE exam_result SET math = 60, chinese = 70
WHERE name = '曹孟德';
为总分后三名数学加30分:
sql复制UPDATE exam_result SET math = math + 30
ORDER BY chinese + math + english LIMIT 3;
警告:不带WHERE条件的UPDATE会更新全表数据!
1.4 数据删除(Delete)
DELETE语句用于删除数据:
sql复制DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
删除示例:
删除孙悟空成绩:
sql复制DELETE FROM exam_result WHERE name = '孙悟空';
删除总分最低的同学:
sql复制DELETE FROM exam_result
ORDER BY english+math+chinese ASC LIMIT 1;
TRUNCATE与DELETE的区别:
sql复制TRUNCATE TABLE table_name;
主要区别:
- TRUNCATE只能操作整表,DELETE可以带条件
- TRUNCATE不记录日志,速度更快但不可回滚
- TRUNCATE会重置AUTO_INCREMENT值
1.5 高级查询技巧
1.5.1 插入查询结果
将查询结果插入到另一表中:
sql复制INSERT INTO table_name [(column [, column ...])] SELECT ...
应用场景: 去重数据
sql复制-- 创建结构相同的空表
CREATE TABLE no_duplicate_table LIKE duplicate_table;
-- 插入去重数据
INSERT INTO no_duplicate_table
SELECT DISTINCT * FROM duplicate_table;
1.5.2 聚合函数
常用聚合函数:
| 函数 | 说明 |
|---|---|
| COUNT | 计数 |
| SUM | 求和 |
| AVG | 平均值 |
| MAX | 最大值 |
| MIN | 最小值 |
使用示例:
统计学生人数:
sql复制SELECT COUNT(*) FROM students;
统计数学成绩平均分:
sql复制SELECT AVG(math) FROM exam_result;
查询英语最高分:
sql复制SELECT MAX(english) FROM exam_result;
注意:WHERE子句不能直接使用聚合函数
1.5.3 GROUP BY分组
GROUP BY用于分组统计:
sql复制SELECT column1, column2, .. FROM table GROUP BY column;
实际案例:
按部门统计员工数:
sql复制SELECT deptno, COUNT(*) FROM emp GROUP BY deptno;
2. 实战经验与注意事项
2.1 性能优化建议
- 避免全列查询:特别是大表,只查询需要的列
- 合理使用索引:WHERE条件中的列建议建立索引
- 分页查询优化:大数据量分页使用WHERE id > ? LIMIT n
- 批量操作:INSERT多行数据时,使用多VALUES语法
2.2 常见问题排查
问题1:别名不能在WHERE中使用
sql复制-- 错误写法
SELECT name, chinese+math+english AS total
FROM exam_result
WHERE total < 200;
-- 正确写法
SELECT name, chinese+math+english AS total
FROM exam_result
WHERE chinese+math+english < 200;
原因:SQL执行顺序是WHERE→SELECT,WHERE执行时别名还未生成
问题2:NULL值比较
sql复制-- 错误写法
SELECT * FROM students WHERE qq = NULL;
-- 正确写法
SELECT * FROM students WHERE qq IS NULL;
2.3 最佳实践
- 重要操作前备份数据:特别是UPDATE和DELETE
- 使用事务:确保数据操作的原子性
- 写完整的WHERE条件:避免误操作全表数据
- 生产环境慎用TRUNCATE:无法回滚且重置自增值
掌握这些基础的CRUD操作是数据库使用的第一步,在实际工作中,还需要结合索引、事务、锁等高级特性来保证数据操作的效率和安全性。希望本文的详细讲解能帮助你建立扎实的MySQL基础。