第二
一、本章核心能力目标(考什么?)
第2章主要考查你对 数据库和表的"定义"能力(DDL语言)。具体包括:
-
数据库的增删改查:创建、查看、选择、修改、删除。
-
数据表的增删改查:创建、查看、修改(加字段/改类型/改位置/改名/删字段)、删除。
-
数据类型:尤其是 DECIMAL、CHAR vs VARCHAR、DATETIME 等。
-
表的约束:NOT NULL、UNIQUE、PRIMARY KEY、DEFAULT、AUTO_INCREMENT。
-
上机实践(图书管理系统案例)对应综合应用。
二、必须默写的SQL语法(简答/填空/改错必出)
1. 数据库操作
sql
-- 创建数据库(带字符集)
CREATE DATABASE [IF NOT EXISTS] db_name [CHARACTER SET utf8mb4];
-- 查看所有数据库
SHOW DATABASES;
-- 查看创建数据库的语句
SHOW CREATE DATABASE db_name;
-- 选择数据库
USE db_name;
-- 修改数据库字符集
ALTER DATABASE db_name CHARACTER SET gbk;
-- 删除数据库
DROP DATABASE [IF EXISTS] db_name;
2. 数据表操作(核心中的核心)
sql
-- 创建表(带约束)
CREATE TABLE 表名 (
字段1 数据类型 [约束],
字段2 数据类型 [约束],
...
[表级约束]
);
-- 查看所有表
SHOW TABLES;
-- 查看建表语句
SHOW CREATE TABLE 表名;
-- 查看表结构(两种等价)
DESC 表名;
DESCRIBE 表名;
-- 修改表名(注意:MySQL 中 RENAME TO 不需要加“TO”?PPT 中写的是 RENAME TO,实际上两种都可以,但考试以教材为准)
ALTER TABLE 旧表名 RENAME TO 新表名;
-- 或者
RENAME TABLE 旧表名 TO 新表名;
-- 添加字段
ALTER TABLE 表名 ADD 新字段名 数据类型 [FIRST|AFTER 字段];
-- 修改字段类型(MODIFY)
ALTER TABLE 表名 MODIFY 字段名 新数据类型 [位置];
-- 修改字段名及类型(CHANGE)
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新数据类型 [位置];
-- 删除字段
ALTER TABLE 表名 DROP 字段名;
-- 删除表
DROP TABLE [IF EXISTS] 表名;
⚠️ 易错点:
MODIFY只能改数据类型和位置,不能改字段名。
CHANGE可以同时改字段名和类型,但必须把旧名和新名都写全。修改表名时,不要写成
RENAME TO写成RENAME就错 (PPT 中用了RENAME TO,但 MySQL 语法是RENAME TABLE ... TO ...或ALTER TABLE ... RENAME TO ...,请以教材示例为准)。
三、数据类型------考选择/判断
| 类型分类 | 具体类型 | 考试要点 |
|---|---|---|
| 数值 | INT, DECIMAL(M,D), FLOAT, DOUBLE | DECIMAL是精确小数(金融用),FLOAT/DOUBLE是近似值。 |
| 日期时间 | DATE, TIME, DATETIME, TIMESTAMP | DATETIME 最常用;上机实践 book 表中用了 DATETIME。 |
| 字符串 | CHAR(n), VARCHAR(n), TEXT | CHAR定长,VARCHAR变长。CHAR效率略高,VARCHAR省空间。 |
| 二进制 | BINARY, BLOB | 了解即可,很少单独考。 |
判断题常考: ❌ "DECIMAL 是浮点数类型"------错,它是定点数。 ❌ "CHAR 和 VARCHAR 都可以存储 255 个字符且占用空间相同"------错,CHAR固定长度,VARCHAR变长。
四、约束------简答/填空/改错高频
| 约束 | 关键字 | 特点 | 删除方式 |
|---|---|---|---|
| 非空 | NOT NULL |
字段不能为 NULL | ALTER TABLE ... MODIFY ... 去掉 NOT NULL |
| 唯一 | UNIQUE |
值不能重复(允许 NULL) | ALTER TABLE ... DROP INDEX 约束名 |
| 主键 | PRIMARY KEY |
唯一 + 非空,一张表只能一个 | ALTER TABLE ... DROP PRIMARY KEY |
| 默认 | DEFAULT 值 |
未指定时自动填默认值 | ALTER TABLE ... CHANGE ... 去掉 DEFAULT |
| 自动增长 | AUTO_INCREMENT |
自增,必须配合主键或唯一键 | 修改字段去掉 AUTO_INCREMENT |
联合主键写法(表级约束):
sql
CREATE TABLE 表名 ( id INT, name VARCHAR(20), PRIMARY KEY (id, name) -- 两个字段共同作为主键 );⚠️ 两个字段之间用 逗号,不是分号。
判断题常考: ✅ "PRIMARY KEY 字段不能为 NULL 也不能重复"------对。 ❌ "一个表可以有多个 PRIMARY KEY"------错,只能有一个。 ✅ "UNIQUE 约束允许 NULL 值"------对(但只能有一个 NULL,MySQL 中多个 NULL 不算重复)。
五、本章未标但可能考到的"小细节"
老师可能只标了大框架,下面这些细节也容易出选择/判断:
-
\G结尾符 (PPT 2.3.2 多学一招): 当字段很多时,使用SELECT * FROM 表名\G可以让结果纵向显示,更美观。可能考:下列哪个选项可以让结果纵向显示?选
\G。 -
修改字段位置:
-
FIRST:放到第一列 -
AFTER 字段名:放到某字段后面 示例:ALTER TABLE dept MODIFY deptno INT AFTER dname;
-
-
AUTO_INCREMENT 初始值 : 默认从 1 开始,不是 0。
判断题:"AUTO_INCREMENT 从 0 开始"------错。
-
外键约束(FOREIGN KEY): 本章只提了一句,但复习指南中未强调,可能出现在选择题。 了解:外键用于建立表之间引用关系,保证数据完整性。
-
删除数据表 :
DROP TABLE IF EXISTS 表名不会报错(如果表不存在则静默跳过)。
第六
下面我按照 必背语法 → 核心概念(含未标细节)→ 易混淆对比 → 复习策略 → 自测题 的顺序指导你。
一、本章核心能力目标(考什么?)
-
说出6种索引类型及各自特点(简答题高频)。
-
掌握三种创建索引的方式 :建表时、
CREATE INDEX、ALTER TABLE ... ADD INDEX。 -
掌握删除索引 :
ALTER TABLE ... DROP INDEX和DROP INDEX。 -
理解索引的优缺点:提高查询速度,但占用空间、降低写性能。
-
掌握视图的创建、查看、修改、删除及通过视图操作数据(增删改查)。
-
能够使用
EXPLAIN分析查询是否使用索引(选择题/判断题)。
二、必须默写的SQL语法(简答/填空/改错)
1. 创建索引的三种方式
方式一:建表时创建索引(PPT 6.1.2)
sql
CREATE TABLE 表名 (
字段1 数据类型 [约束],
...,
{INDEX|KEY} [索引名] (字段列表), -- 普通索引
UNIQUE [INDEX|KEY] [索引名] (字段列表), -- 唯一索引
PRIMARY KEY (字段列表), -- 主键索引
FULLTEXT [INDEX|KEY] [索引名] (字段列表), -- 全文索引
SPATIAL [INDEX|KEY] [索引名] (字段列表) -- 空间索引
);
方式二:使用 CREATE INDEX 语句(已存在的表)
sql
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX 索引名
ON 表名 (字段列表);
方式三:使用 ALTER TABLE 语句(已存在的表)
sql
ALTER TABLE 表名
ADD {INDEX|KEY} [索引名] (字段列表), -- 普通
ADD UNIQUE [INDEX|KEY] [索引名] (字段列表), -- 唯一
ADD PRIMARY KEY (字段列表), -- 主键
ADD FULLTEXT [INDEX|KEY] [索引名] (字段列表), -- 全文
ADD SPATIAL [INDEX|KEY] [索引名] (字段列表); -- 空间
2. 删除索引的两种方式
sql
-- 方式一
ALTER TABLE 表名 DROP INDEX 索引名;
-- 方式二(不能删除主键索引,主键用 ALTER TABLE ... DROP PRIMARY KEY)
DROP INDEX 索引名 ON 表名;
3. 查看索引
sql
SHOW INDEX FROM 表名; -- 查看所有索引信息
SHOW CREATE TABLE 表名; -- 查看建表语句(含索引)
4. 视图操作
sql
-- 创建视图
CREATE [OR REPLACE] VIEW 视图名 [(字段列表)] AS SELECT语句;
-- 查看视图定义
SHOW CREATE VIEW 视图名;
-- 查看视图字段
DESC 视图名;
-- 修改视图(两种方式)
CREATE OR REPLACE VIEW ...; -- 替换
ALTER VIEW 视图名 ...; -- 修改定义
-- 删除视图
DROP VIEW 视图名 [, 视图名2...];
5. 通过视图操作数据(与表类似)
sql
INSERT INTO 视图名 VALUES(...);
UPDATE 视图名 SET ... WHERE ...;
DELETE FROM 视图名 WHERE ...;
注意:视图是否能成功增删改取决于视图定义(如多表视图通常不可插入/更新)。
三、6种索引类型(简答题必背清单)
根据PPT和复习指南,你需要能列出至少4种并说明特点:
| 索引类型 | 关键字 | 特点 | 允许NULL | 允许重复 |
|---|---|---|---|---|
| 普通索引 | INDEX / KEY | 基本索引,无限制 | 是 | 是 |
| 唯一索引 | UNIQUE INDEX | 索引列值必须唯一 | 是(只能一个NULL) | 否 |
| 主键索引 | PRIMARY KEY | 唯一+非空,一张表只能一个 | 否 | 否 |
| 全文索引 | FULLTEXT | 用于大文本字段的快速搜索 | 是 | 是 |
| 空间索引 | SPATIAL | 用于地理空间数据类型(如GEOMETRY) | 否 | 是 |
| 单列/复合 | (按列数分) | 单列索引 vs 多个字段组成的复合索引 | - | - |
老师可能没标但你需记:
复合索引遵循 最左前缀原则(查询条件必须包含索引的最左列才能有效)。
创建唯一索引时,表中该列不能有重复值,否则报错。
空间索引的字段必须为
NOT NULL(PPT中address GEOMETRY NOT NULL)。
四、未标但可能考的小细节(选择题/判断题高频)
-
索引的缺点:
-
占用磁盘空间;
-
降低增删改的速度(因为要维护索引);
-
创建和维护索引耗时随数据量增加而增加。
判断:"索引越多越好"------错。
-
-
EXPLAIN关键字:-
用于分析
SELECT/UPDATE/DELETE/INSERT/REPLACE是否使用索引; -
结果中的
key列显示实际使用的索引,possible_keys显示可能使用的索引。
可能考:下列哪个语句可以查看索引是否被使用?选
EXPLAIN SELECT ... -
-
SHOW INDEX FROM结果中的重要字段:-
Non_unique:0表示唯一索引,1表示非唯一。 -
Key_name:索引名。 -
Column_name:索引列。 -
Index_type:BTREE/HASH等。
-
-
复合索引的最左前缀原则:
-
例:
INDEX (a, b, c) -
查询
WHERE a=1→ 使用索引;WHERE a=1 AND b=2→ 使用索引;WHERE b=2→ 不使用索引(缺少最左列a)。 -
设计时应把最常用的字段放在最左边。
-
-
视图的
OR REPLACE:-
如果视图已存在则替换定义,不存在则创建。
-
与
ALTER VIEW功能类似,但CREATE OR REPLACE更常用。
-
-
通过视图更新数据的限制:
-
如果视图包含聚合函数、
DISTINCT、GROUP BY、HAVING、UNION或来自多表(除非使用INSTEAD OF触发器,但MySQL不支持),通常不能更新。 -
考试可能考:"所有视图都可以直接通过INSERT添加数据"------错。
-
-
删除视图不影响基本表(判断题常考)。
-
索引的可见性 (PPT中有
Visible: YES字段):MySQL 8.0 支持不可见索引(优化测试用),一般了解即可。
五、易混淆对比(重点记忆)
1. CREATE INDEX vs ALTER TABLE ... ADD INDEX
-
两者功能几乎相同,但
ALTER TABLE可以同时添加多个索引(用逗号分隔),CREATE INDEX一次只能创建一个。 -
ALTER TABLE还可以添加主键(ADD PRIMARY KEY),CREATE INDEX不能。
2. DROP INDEX vs ALTER TABLE ... DROP INDEX
- 等效,但
DROP INDEX不能删除主键,主键需用ALTER TABLE ... DROP PRIMARY KEY。
3. 唯一索引 vs 主键索引
-
主键索引是特殊的唯一索引,但一张表只能有一个主键,可以有多个唯一索引。
-
主键字段不允许 NULL,唯一索引允许一个 NULL。
4. 普通索引 vs 全文索引
- 普通索引用于精确查找或范围查找;全文索引用于
MATCH ... AGAINST进行文本搜索。
六、本章复习策略(按优先级)
🔴 第一优先级(必须亲手敲一遍)
-
三种创建索引的语法 (尤其是
CREATE INDEX和ALTER TABLE ADD INDEX)。 -
删除索引的两种写法。
-
6种索引类型的名称和特点(能写出至少4种)。
-
视图的创建和查看 (
CREATE VIEW ... AS SELECT)。
🟠 第二优先级(理解并记住易错点)
-
最左前缀原则(选择题)。
-
EXPLAIN的作用和关键列(key)。 -
通过视图操作数据的限制。
-
索引的优缺点。
🟡 第三优先级(浏览,防止冷门)
-
空间索引(了解需要
GEOMETRY类型,且NOT NULL)。 -
SHOW INDEX FROM各字段含义(Non_unique、Collation等)。 -
视图的
ALTER VIEW语法。
七、自测题(检验掌握程度)
单选题
-
下列哪种索引要求字段值不能重复且不能为NULL? A. UNIQUE INDEX B. PRIMARY KEY C. INDEX D. FULLTEXT 答案:B
-
在已有表
student的name列上创建普通索引idx_name,正确的语句是: A.CREATE INDEX idx_name ON student(name);B.CREATE INDEX idx_name student(name);C.ALTER TABLE student ADD INDEX idx_name(name);D. A和C都正确 答案:D -
关于复合索引
INDEX (a, b, c),以下哪个查询不能 使用该索引? A.WHERE a = 1B.WHERE a = 1 AND c = 3C.WHERE b = 2 AND a = 1D.WHERE b = 2答案:D(缺少最左列a)
判断题
-
( )创建唯一索引时,如果表中已有重复数据,仍可成功创建。 错(会报错,需先清理重复数据)。
-
( )视图是虚拟表,删除视图会同时删除基本表中的数据。 错(只删除视图定义,不影响基本表)。
-
( )使用
EXPLAIN SELECT ...可以查看MySQL是否使用了索引。 对。
简答题(模拟考试)
-
请列出MySQL中至少4种索引类型,并说明每种索引的特点。 (参考上面的表格,写出普通、唯一、主键、全文即可)
-
请写出在已有表
emp的ename和deptno字段上创建复合唯一索引uniq_ename_dept的两种SQL语句。sql
-- 方式1 CREATE UNIQUE INDEX uniq_ename_dept ON emp(ename, deptno); -- 方式2 ALTER TABLE emp ADD UNIQUE INDEX uniq_ename_dept(ename, deptno);
第四
一、本章核心能力目标(考什么?)
-
熟记 SELECT 语句的完整语法顺序(FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT),顺序写错即错。
-
掌握 DISTINCT 去重:作用在多个字段时,组合去重。
-
掌握条件查询 :比较运算符(
=,<>,<,>,>=,<=)、IN、IS NULL、LIKE(%和_通配符及转义)。 -
掌握逻辑运算符 :
AND,OR,NOT,以及AND优先级高于OR。 -
掌握聚合函数 :
COUNT,SUM,AVG,MAX,MIN,特别注意COUNT(*)与COUNT(字段)的区别(后者忽略 NULL)。 -
掌握分组查询 :
GROUP BY+ 聚合函数,以及HAVING对分组后结果过滤(HAVING可以使用聚合函数,WHERE不能)。 -
掌握排序 :
ORDER BY默认 ASC,多个字段排序规则,NULL视为最小值。 -
掌握限量查询 :
LIMIT [偏移量,] 记录数,偏移量从 0 开始。 -
了解常用内置函数 :
CONCAT,IF,IFNULL等(选择题可能出现)。 -
掌握别名 :表别名和字段别名的
AS可省略。
二、必须默写的 SELECT 语法结构(填空/改错高频)
sql
SELECT [DISTINCT] 字段1 [AS 别名1], 字段2 [AS 别名2], 聚合函数(...)
FROM 表名 [AS 表别名]
[WHERE 条件表达式] -- 分组前过滤,不能使用聚合函数
[GROUP BY 分组字段1, 分组字段2]
[HAVING 分组后过滤条件] -- 可以使用聚合函数
[ORDER BY 排序字段1 [ASC|DESC], 排序字段2 [ASC|DESC]]
[LIMIT [偏移量,] 记录数];
⚠️ 重要 :各个子句的顺序绝对不能错 。例如
WHERE必须在GROUP BY之前,ORDER BY必须在LIMIT之前。
三、老师可能没标但你需掌握的细节(选择题/判断题高频)
1. DISTINCT 作用于多个字段
-
SELECT DISTINCT 字段1, 字段2 FROM ...:只有字段1和字段2的值都相同才被去重。 -
判断:"DISTINCT 只能作用于一个字段" ------ 错。
2. 比较运算符与 NULL
-
任何与
NULL的比较(= NULL,<> NULL)结果都是 NULL(未知),不会返回任何行。 -
判断
NULL必须使用IS NULL或IS NOT NULL。 -
示例:
SELECT * FROM emp WHERE comm = NULL;结果为空(错误写法)。
3. LIKE 的通配符及转义
-
%匹配任意长度(包括0个)字符;_匹配单个字符。 -
如果要查询的字符串本身包含
%或_,需要用\转义,例如'%\%%'表示包含%的字符串。 -
示例:
WHERE ename LIKE '%\%%'查询姓名中含有%的员工。
4. AND 和 OR 的优先级
-
AND优先级高于OR。如果不加括号,会先计算AND两侧的条件。 -
示例:
WHERE ename='刘一' OR ename='李四' AND deptno=30实际等价于ename='刘一' OR (ename='李四' AND deptno=30),与直觉可能不同。 -
建议:混合使用时加括号明确逻辑。
5. BETWEEN ... AND ... 包含边界
-
WHERE sal BETWEEN 2000 AND 3000等价于sal >= 2000 AND sal <= 3000,包含两端。 -
NOT BETWEEN则排除边界。
6. 聚合函数的注意事项
-
COUNT(*)统计所有行(包括 NULL);COUNT(字段)统计该字段非 NULL 的行数。 -
AVG()自动忽略 NULL 值,若希望将 NULL 当作 0 计算,需先用IFNULL(字段,0)转换。 -
聚合函数不能直接出现在 WHERE 子句中 。例如
WHERE AVG(sal) > 3000是错误的。 -
需要过滤聚合结果时,必须使用
HAVING。
7. GROUP BY 的常见陷阱
-
如果
SELECT中出现了非分组字段(且没有聚合函数),MySQL 在某些模式下会报错或返回不确定值。考试可能考:"SELECT 的字段必须全部包含在 GROUP BY 中或使用聚合函数" ------ 对(严格 SQL 模式)。 -
分组后查询的字段通常是分组字段 + 聚合函数。
8. HAVING vs WHERE
-
WHERE在分组前过滤行,不能使用聚合函数。 -
HAVING在分组后过滤组,可以使用聚合函数。 -
示例:
SELECT deptno, AVG(sal) FROM emp GROUP BY deptno HAVING AVG(sal) > 3000;
9. ORDER BY 细节
-
默认升序(
ASC),降序用DESC。 -
可以对多个字段排序:
ORDER BY job ASC, empno DESC。 -
NULL在排序中视为最小值(升序时排在最前,降序时排在最后)。 -
判断:"ORDER BY 只能按一个字段排序" ------ 错。
10. LIMIT 的两种用法
-
LIMIT 5:返回前 5 行(等价于LIMIT 0,5)。 -
LIMIT 3,5:从第 4 行开始(偏移量 0 表示第一行),返回 5 行。 -
注意:偏移量从 0 开始,不是 1。
-
示例:查询工资第 2~5 名:
ORDER BY sal DESC LIMIT 1,4。
11. 常用内置函数(可能考选择题)
-
CONCAT(str1, str2, ...):连接字符串。 -
IF(expr, true_value, false_value):条件判断。 -
IFNULL(expr, default_value):若 expr 为 NULL 则返回默认值。 -
例如:
SELECT IFNULL(comm, 0) FROM emp;
12. 别名(AS 可省略)
-
表别名:
FROM emp e等价于FROM emp AS e。 -
字段别名:
SELECT ename AS name等价于SELECT ename name。 -
注意:别名中如果包含空格或特殊字符,需要用单引号或反引号括起来。
四、易混淆对比(重点记忆)
| 对比项 | 说明 | 示例 |
|---|---|---|
COUNT(*) vs COUNT(字段) |
* 包含 NULL 行;字段 忽略 NULL |
COUNT(comm) 只统计非 NULL 奖金 |
WHERE vs HAVING |
WHERE 过滤行(分组前);HAVING 过滤组(分组后) | WHERE sal>1000;HAVING AVG(sal)>2000 |
AND vs OR 优先级 |
AND 先于 OR 计算 | 见上文 |
BETWEEN vs 连续 AND |
效果相同,BETWEEN 更简洁 | sal BETWEEN 2000 AND 3000 |
LIKE '%' vs = |
= 精确匹配,LIKE 可带通配符 |
ename='张三';ename LIKE '张%' |
LIMIT 偏移量 |
第 1 条记录偏移 0,第 2 条偏移 1 | LIMIT 2,3 返回第 3,4,5 条 |
五、上机实践指导(紧扣期末可能题型)
PPT 4.6 节的图书管理系统案例非常典型,覆盖了 WHERE、ORDER BY、LIMIT、LIKE、IN、BETWEEN 等。建议你亲手敲一遍下面几个核心查询:
sql
-- 1. 查询可借阅图书(state=0)的名称和上架时间
SELECT name, upload_time FROM book WHERE state = 0;
-- 2. 按名称升序排序,取前5条的名称、价格、状态
SELECT name, price, state FROM book ORDER BY name ASC LIMIT 5;
-- 3. 价格大于50的图书名称和价格
SELECT name, price FROM book WHERE price > 50;
-- 4. 价格在30到50之间的图书(包含边界)
SELECT name, price FROM book WHERE price BETWEEN 30 AND 50;
-- 5. 已借阅图书(state=1)的名称、借阅人编号、借阅时间
SELECT name, borrower_id, borrow_time FROM book WHERE state = 1;
-- 6. 名称包含“Java”的图书名称
SELECT name FROM book WHERE name LIKE '%Java%';
-- 7. 名称以“入门”结尾的图书名称
SELECT name FROM book WHERE name LIKE '%入门';
-- 8. 名称为“西游记”或“红楼梦”的图书名称和价格
SELECT name, price FROM book WHERE name IN('西游记','红楼梦');
老师可能不标但你需注意:
第4个查询中
BETWEEN 30 AND 50包含边界值。第6、7个查询中
%的位置不同,含义不同(包含 vs 结尾)。第8个查询中
IN等价于多个OR条件。
六、自测题(检验掌握程度)
单选题
-
下列哪个子句必须出现在
GROUP BY之后? A.WHEREB.HAVINGC.ORDER BYD.LIMIT答案:B (HAVING只能跟在GROUP BY后面) -
查询员工表中平均工资大于3000的部门,正确的语句是: A.
SELECT deptno, AVG(sal) FROM emp WHERE AVG(sal)>3000 GROUP BY deptno;B.SELECT deptno, AVG(sal) FROM emp GROUP BY deptno HAVING AVG(sal)>3000;C.SELECT deptno, AVG(sal) FROM emp HAVING AVG(sal)>3000 GROUP BY deptno;D.SELECT deptno, AVG(sal) FROM emp GROUP BY deptno WHERE AVG(sal)>3000;答案:B -
关于
LIMIT 3,5的说法正确的是: A. 返回第3到第5条记录 B. 返回前3条记录 C. 返回从第4条开始的5条记录 D. 返回第3条后的5条记录 答案:C -
查询姓名以"张"开头且名字长度为2个字的员工(假设中文字符占一个字符),应使用: A.
WHERE ename LIKE '张_'B.WHERE ename LIKE '张%'C.WHERE ename = '张_'D.WHERE ename LIKE '张__'答案:A (_匹配单个字符) -
关于
COUNT(*)和COUNT(comm)的区别,说法正确的是: A. 两者结果完全相同 B.COUNT(comm)统计包括 NULL 的行数 C.COUNT(*)统计所有行,COUNT(comm)忽略 comm 为 NULL 的行 D.COUNT(*)比COUNT(comm)慢 答案:C
判断题
-
( )
WHERE子句中可以使用SUM()函数进行条件过滤。 错(聚合函数不能直接用在 WHERE 中) -
( )
ORDER BY默认按升序排序,NULL值在升序中排在最后。 错 (NULL被视为最小值,排在升序的最前面) -
( )
SELECT DISTINCT ename, job表示查询结果中 ename 唯一,job 可以重复。 错(两个字段的组合值唯一才去重) -
( )
LIMIT 0,10和LIMIT 10返回的结果相同。 对(偏移量0可省略) -
( )
SELECT ename, sal FROM emp ORDER BY sal;默认按 sal 降序排列。 错(默认升序 ASC)
简答题(模拟考试)
-
请写出 SELECT 语句中各子句(FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT)的正确顺序,并简述 WHERE 和 HAVING 的区别。 参考答案 : 顺序:
FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT。 区别:WHERE在分组前对行进行过滤,不能使用聚合函数;HAVING在分组后对组进行过滤,可以使用聚合函数。 -
写出查询员工表 emp 中,平均工资低于2500的部门编号及其平均工资的 SQL 语句。
sql
SELECT deptno, AVG(sal) AS avg_sal FROM emp GROUP BY deptno HAVING AVG(sal) < 2500;第五
一、本章核心能力目标(考什么?)
-
理解交叉连接(笛卡尔积) 及其产生的结果行数(表1行数 × 表2行数)。
-
掌握内连接 :
[INNER] JOIN ... ON,只返回匹配的记录。 -
掌握外连接 :
LEFT JOIN(左表全保留)和RIGHT JOIN(右表全保留)。 -
掌握自连接:同一张表通过别名连接,常用于查询"同部门员工"等。
-
掌握子查询的四种用法 :
IN、EXISTS、ANY/SOME、ALL,以及与比较运算符结合的子查询。 -
理解外键约束 :添加、删除,以及级联操作(
ON DELETE CASCADE等)。 -
掌握关联表的插入/删除顺序:先主表后从表(插入),先删从表再删主表(删除)。
二、必须默写的核心语法
1. 交叉连接(笛卡尔积)
sql
SELECT * FROM 表1 CROSS JOIN 表2; -- 等价于 SELECT * FROM 表1, 表2;注意 :如果没有
WHERE条件,返回的就是两表行数的乘积,通常是无意义的。2. 内连接
sql
SELECT 字段 FROM 表1 [INNER] JOIN 表2 ON 表1.关联字段 = 表2.关联字段;-
INNER可省略。 -
也可以使用
WHERE条件实现内连接(老式写法):FROM 表1, 表2 WHERE 条件,但推荐使用JOIN ... ON。
3. 外连接(左/右)
sql
-- 左连接:左表所有行 + 右表匹配的行 SELECT 字段 FROM 左表 LEFT JOIN 右表 ON 条件; -- 右连接:右表所有行 + 左表匹配的行 SELECT 字段 FROM 左表 RIGHT JOIN 右表 ON 条件;4. 自连接(内连接的一种特殊形式)
sql
SELECT e1.* FROM emp e1 JOIN emp e2 ON e1.deptno = e2.deptno WHERE e2.ename = '王五';5. 子查询
5.1
IN/NOT INsql
SELECT * FROM dept WHERE deptno IN (SELECT deptno FROM emp WHERE sal > 2900);5.2
EXISTS/NOT EXISTSsql
SELECT * FROM dept WHERE EXISTS (SELECT 1 FROM emp WHERE emp.deptno = dept.deptno AND emp.sal > 2900);-
EXISTS只关心子查询是否有行返回,不关心具体值。 -
外层查询的每一行都会执行子查询(关联子查询)。
5.3
ANY(或SOME)sql
SELECT * FROM emp WHERE deptno=10 AND sal > ANY(SELECT sal FROM emp WHERE deptno=20);> ANY表示大于子查询中的最小值。
5.4
ALLsql
SELECT * FROM emp WHERE deptno=10 AND sal > ALL(SELECT sal FROM emp WHERE deptno=20);> ALL表示大于子查询中的最大值。
5.5 比较运算符直接使用子查询(子查询返回单值)
sql
SELECT * FROM emp WHERE job = (SELECT job FROM emp WHERE ename = '王五');6. 外键约束
添加外键
sql
ALTER TABLE 从表 ADD CONSTRAINT 外键名 FOREIGN KEY (外键字段) REFERENCES 主表(主键字段) [ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}] [ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}];删除外键
sql
ALTER TABLE 从表 DROP FOREIGN KEY 外键名;
三、老师可能没标但你需掌握的细节(选择题/判断题高频)
1. 交叉连接(笛卡尔积)的实用性
-
交叉连接如果不加过滤条件,结果数 = 表1行数 × 表2行数。实际业务中很少直接使用,但它是内连接/外连接的基础。
-
判断:"交叉连接返回的是两表中匹配的记录" ------ 错,它返回所有组合。
2. 内连接与
WHERE多表等价性FROM A JOIN B ON A.id = B.id与FROM A, B WHERE A.id = B.id在功能上等价,但推荐使用JOIN语法,更清晰。
3. 自连接必须使用别名
-
同一张表在
FROM中出现两次,必须给至少一个表起别名,否则会报错。 -
示例:
SELECT * FROM emp e1, emp e2 WHERE e1.deptno = e2.deptno。
4. 左/右连接中,ON 条件与 WHERE 条件的区别
-
ON决定如何匹配两表;WHERE对连接后的结果进行过滤。 -
外连接中,
ON条件不会过滤左表(或右表)的全部记录,但WHERE可能会把左表中不满足条件的行也过滤掉。 -
易错点:想要保留左表所有记录,过滤条件应放在
ON中,而不是WHERE。
5. 子查询的两种类型
-
不相关子查询 :子查询可以独立运行,例如
SELECT deptno FROM emp WHERE sal>2900。 -
相关子查询 :子查询中使用了外层查询的字段,例如
EXISTS子查询中的emp.deptno = dept.deptno。相关子查询对外层每一行都执行一次。
6.
IN与EXISTS的性能选择(考试可能考判断)-
当外表大、内表小 时,适合用
IN(因为IN先执行子查询,生成结果集后再匹配)。 -
当外表小、内表大 时,适合用
EXISTS(因为EXISTS对外表每一行执行子查询,可以利用内表索引)。 -
判断:"
IN子查询总是比EXISTS快" ------ 错,取决于数据分布。
7.
ANY与ALL的等价写法-
> ANY (子查询)等价于> MIN(子查询)。 -
< ANY等价于< MAX(子查询)。 -
> ALL等价于> MAX(子查询)。 -
< ALL等价于< MIN(子查询)。 -
常考:查询工资高于部门20中任意一个人的工资 → 使用
> ANY或> MIN。
8. 子查询返回空值时的行为
-
NOT IN (空集)会返回FALSE?实际:如果子查询结果中包含NULL,NOT IN会返回空(因为NULL比较的结果为UNKNOWN)。所以使用NOT IN时要确保子查询结果不含NULL,否则可能得不到预期结果。 -
安全做法:在子查询中使用
WHERE 字段 IS NOT NULL,或改用NOT EXISTS。
9. 外键约束的存储引擎要求
-
MySQL 中只有 InnoDB 引擎支持外键约束。MyISAM 不支持。
-
判断:"所有存储引擎都支持外键" ------ 错。
10. 外键约束的级联操作
-
ON DELETE CASCADE:删除主表记录时,自动删除从表中引用该记录的行。 -
ON DELETE SET NULL:删除主表记录时,将从表的外键列设为NULL(要求该列允许NULL)。 -
ON DELETE RESTRICT / NO ACTION:如果从表有引用,则阻止删除主表记录(默认行为)。 -
考试可能考:哪种级联操作可以避免"垃圾数据"?
CASCADE或SET NULL。
11. 关联表数据操作的顺序
-
插入:先插入主表(有主键),再插入从表(外键值必须存在于主表)。
-
删除:先删除从表中引用的行,再删除主表的行。否则会违反外键约束。
-
更新主键:如果从表引用了该主键,直接更新会失败,需要级联或先修改从表。
12. 外键名的引号问题
- 定义外键名称时不能加引号:
CONSTRAINT fk_name(正确),CONSTRAINT 'fk_name'(错误)。
四、易混淆对比(重点记忆)
对比项 说明 示例 内连接 vs 外连接 内连接只返回匹配行;外连接返回一侧全部行 LEFT JOIN保留左表所有行左连接 vs 右连接 左连接保留左表,右连接保留右表;两者可互换 A LEFT JOIN B等价于B RIGHT JOIN AINvsEXISTSIN适合内表小;EXISTS适合外表小;EXISTS可处理NULL见上 ANYvsALL> ANY:大于最小值;> ALL:大于最大值> ANY(...)等价于> MIN(...)子查询返回单值 vs 多值 单值可用 =,多值必须用IN/ANY/ALLjob = (子查询)子查询必须返回一行一列删除外键 vs 删除索引 外键需用 DROP FOREIGN KEY,普通索引用DROP INDEXALTER TABLE t DROP FOREIGN KEY fk_nameON DELETE CASCADEvsSET NULLCASCADE 删除从表行;SET NULL 仅将外键设为 NULL -
五、上机实践要点(紧扣期末)
PPT 5.4 节图书管理系统案例覆盖了:
-
多表连接(查询张三借阅的图书)。
-
子查询(比《西游记》价格高、高于平均价、与《三国演义》状态相同)。
-
ANY/ALL子查询(已借阅 vs 未借阅的价格比较)。 -
添加外键(
book.borrower_id引用user.id)。
建议手动敲一遍以下核心查询:
sql
-- 1. 内连接:查询所有员工及其部门名称(已分配部门的) SELECT e.ename, d.dname FROM emp e JOIN dept d ON e.deptno = d.deptno; -- 2. 左连接:查询所有部门及其员工姓名(没有员工的部门也显示) SELECT d.dname, e.ename FROM dept d LEFT JOIN emp e ON e.deptno = d.deptno; -- 3. 自连接:查询与“张三”同部门的员工 SELECT e2.* FROM emp e1 JOIN emp e2 ON e1.deptno = e2.deptno WHERE e1.ename = '张三'; -- 4. 子查询 IN:查询有工资>2900的部门信息 SELECT * FROM dept WHERE deptno IN (SELECT deptno FROM emp WHERE sal > 2900); -- 5. 子查询 EXISTS:同上 SELECT * FROM dept d WHERE EXISTS (SELECT 1 FROM emp e WHERE e.deptno = d.deptno AND e.sal > 2900); -- 6. ANY 子查询:查询部门10中工资高于部门20任意一人的员工 SELECT * FROM emp WHERE deptno=10 AND sal > ANY(SELECT sal FROM emp WHERE deptno=20); -- 7. ALL 子查询:查询部门10中工资高于部门20所有人的员工 SELECT * FROM emp WHERE deptno=10 AND sal > ALL(SELECT sal FROM emp WHERE deptno=20); -- 8. 添加外键 ALTER TABLE book ADD CONSTRAINT FK_borrower FOREIGN KEY (borrower_id) REFERENCES user(id);
六、自测题(检验掌握程度)
单选题
-
下列哪种连接会返回左表的所有记录,即使右表中没有匹配? A.
INNER JOINB.LEFT JOINC.CROSS JOIND.RIGHT JOIN答案:B -
查询与"张三"同部门的员工信息,应使用的连接方式是: A. 左连接 B. 右连接 C. 内连接 + 自连接 D. 交叉连接 答案:C(自连接是内连接的一种)
-
子查询
SELECT * FROM dept WHERE deptno IN (SELECT deptno FROM emp WHERE sal>3000)中,外层查询的 deptno 与子查询的 deptno 的关系是: A. 不相干 B. 相关子查询 C. 同一张表 D. 没有关系 答案:A(这里子查询不依赖外层,是不相关子查询) -
以下哪个关键字必须与比较运算符一起使用? A.
INB.EXISTSC.ANYD.NOT答案:C (ANY/ALL必须与>,<,=等连用) -
在 MySQL 中,以下哪个存储引擎支持外键约束? A. MyISAM B. MEMORY C. InnoDB D. ARCHIVE 答案:C
判断题
-
( )
FROM A, B WHERE A.id = B.id与FROM A JOIN B ON A.id = B.id的效果完全相同。 对(都是内连接) -
( )执行
DELETE FROM dept WHERE deptno=10时,如果员工表中有 deptno=10 的员工且外键约束为默认的RESTRICT,则会自动删除这些员工。 错(会阻止删除,需要先处理从表) -
( )
EXISTS子查询中的SELECT *可以改为SELECT 1或SELECT NULL,结果不变。 对 (EXISTS只检查结果集是否为空,不关心具体值) -
( )使用
NOT IN (子查询)时,如果子查询结果中包含NULL,则整个查询可能返回空结果。 对 (因为NOT IN (NULL, ...)的逻辑结果是UNKNOWN) -
( )左连接查询的结果集行数一定大于等于内连接查询的结果集行数。 对(左连接至少保留左表所有行,内连接只保留匹配行)
简答题(模拟考试)
-
请简述内连接、左外连接、右外连接的区别,并写出左连接的语法。 参考答案:
-
内连接:只返回两表中连接条件匹配的行。
-
左外连接:返回左表所有行,右表不匹配的填
NULL。 -
右外连接:返回右表所有行,左表不匹配的填
NULL。 左连接语法:SELECT ... FROM 表1 LEFT JOIN 表2 ON 条件;
-
-
写出查询"部门平均工资大于3000的部门名称和平均工资"的 SQL 语句,要求使用子查询或连接查询任一方式。
sql
-- 方法1:连接 + 分组 SELECT d.dname, AVG(e.sal) AS avg_sal FROM dept d JOIN emp e ON d.deptno = e.deptno GROUP BY d.deptno, d.dname HAVING AVG(e.sal) > 3000; -- 方法2:子查询(先查出符合条件的部门编号) SELECT dname, (SELECT AVG(sal) FROM emp WHERE deptno = d.deptno) AS avg_sal FROM dept d WHERE d.deptno IN (SELECT deptno FROM emp GROUP BY deptno HAVING AVG(sal) > 3000);
-
第八
一、本章核心能力目标(考什么?)
-
存储过程 :创建(
CREATE PROCEDURE)、调用(CALL)、查看(SHOW PROCEDURE STATUS)、修改(ALTER)、删除(DROP PROCEDURE)。重点掌握IN/OUT/INOUT参数。 -
存储函数 :创建(
CREATE FUNCTION)、调用(SELECT)、删除(DROP FUNCTION)。重点掌握RETURNS和RETURN。 -
变量 :系统变量(全局/会话)、用户变量(
@var)、局部变量(DECLARE)。作用域和赋值方式。 -
流程控制 :
IF、CASE、LOOP、REPEAT、WHILE、LEAVE、ITERATE。 -
错误处理 :
DECLARE ... HANDLER(CONTINUE/EXIT)。 -
游标:声明、打开、获取、关闭,与错误处理配合遍历结果集。
-
触发器 :创建(
CREATE TRIGGER)、触发时机(BEFORE/AFTER)、触发事件(INSERT/UPDATE/DELETE)、NEW/OLD、删除(DROP TRIGGER)。
二、必须默写的核心语法
1. 存储过程
sql
-- 创建
DELIMITER //
CREATE PROCEDURE 过程名 ([IN|OUT|INOUT 参数名 类型])
[特征...]
BEGIN
-- SQL语句
END //
DELIMITER ;
-- 调用
CALL 过程名(参数值, @输出变量);
-- 查看状态
SHOW PROCEDURE STATUS LIKE '过程名';
-- 查看创建语句
SHOW CREATE PROCEDURE 过程名;
-- 删除
DROP PROCEDURE [IF EXISTS] 过程名;
2. 存储函数
sql
-- 创建
DELIMITER //
CREATE FUNCTION 函数名(参数名 类型)
RETURNS 返回类型
[特征...]
BEGIN
RETURN (SELECT ...);
END //
DELIMITER ;
-- 调用
SELECT 函数名(参数值);
-- 删除
DROP FUNCTION [IF EXISTS] 函数名;
3. 变量
sql
-- 用户变量(以@开头,会话级)
SET @var = 10;
SELECT @var := 列名 FROM ...;
SELECT 列名 INTO @var FROM ...;
-- 局部变量(必须在 BEGIN...END 中,且必须在游标和错误处理程序之前声明)
DECLARE var_name 类型 [DEFAULT 默认值];
4. 流程控制
sql
-- IF
IF 条件 THEN
...
ELSEIF 条件 THEN
...
ELSE
...
END IF;
-- CASE(两种形式)
CASE 表达式
WHEN 值1 THEN ...
WHEN 值2 THEN ...
ELSE ...
END CASE;
CASE
WHEN 条件1 THEN ...
WHEN 条件2 THEN ...
ELSE ...
END CASE;
-- LOOP(需配合 LEAVE 退出)
[标签:] LOOP
IF 条件 THEN LEAVE 标签; END IF;
END LOOP 标签;
-- REPEAT(至少执行一次,条件为真退出)
[标签:] REPEAT
...
UNTIL 条件
END REPEAT 标签;
-- WHILE(条件为假时进入循环?注意:WHILE 条件为真时执行)
[标签:] WHILE 条件 DO
...
END WHILE 标签;
-- 跳转
LEAVE 标签; -- 退出整个循环
ITERATE 标签; -- 跳过本次循环剩余语句,开始下一次循环
5. 错误处理
sql
-- 自定义错误名称
DECLARE 错误名称 CONDITION FOR SQLSTATE '23000'; -- 或 1062
-- 错误处理程序
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET mark = 1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ... END;
6. 游标
sql
-- 声明游标(必须在局部变量之后,错误处理程序之前)
DECLARE 游标名 CURSOR FOR SELECT ...;
-- 打开
OPEN 游标名;
-- 获取一行
FETCH 游标名 INTO 变量1, 变量2, ...;
-- 关闭
CLOSE 游标名;
7. 触发器
sql
-- 创建
CREATE TRIGGER 触发器名
{BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名
FOR EACH ROW
BEGIN
-- 可使用 NEW.列名(INSERT/UPDATE时新值)和 OLD.列名(UPDATE/DELETE时旧值)
END;
-- 查看
SHOW TRIGGERS;
SELECT * FROM information_schema.triggers WHERE trigger_name = '...';
-- 删除
DROP TRIGGER [IF EXISTS] [数据库名.]触发器名;
三、老师可能没标但你需掌握的细节(选择题/判断题高频)
1. 存储过程的参数模式
-
IN:输入参数,调用时传入值(可以是常量或变量),过程内部可修改但不返回。 -
OUT:输出参数,过程内部修改后返回给调用者(初始值为NULL)。 -
INOUT:输入输出参数,既传入值,又可修改后返回。 -
调用时,对于
OUT和INOUT,必须使用变量 (如@var)接收返回值。
2. 存储函数与存储过程的区别(简答高频)
-
存储过程没有返回值 (或者说通过
OUT参数返回多个值),存储函数必须返回一个值 (通过RETURN)。 -
存储过程用
CALL调用,存储函数用SELECT调用(就像内置函数)。 -
存储函数可以在 SQL 表达式中使用(如
SELECT func(col) FROM ...),存储过程不能。
3. DELIMITER 的作用
-
默认
;结束语句,但在存储过程/函数体中可能包含多条语句,需要临时改变分隔符,以便整个过程被当成一个语句提交。常用DELIMITER //然后以//结尾,最后恢复DELIMITER ;。 -
判断:"创建存储过程时,必须使用
DELIMITER命令"------错(在命令行或某些工具中可能需要,但在某些图形界面中可省略,但考试常考其作用)。
4. 变量的作用域
-
系统变量 :
GLOBAL影响整个服务器,SESSION影响当前连接。修改全局变量后新连接生效,当前已连接的会话不受影响(除非再修改会话变量)。 -
用户变量 :以
@开头,会话级,可以在任何地方使用(甚至跨存储过程)。 -
局部变量 :用
DECLARE声明,仅在BEGIN...END块内有效,且必须在块的开头(变量声明必须在游标、条件、处理程序之前)。局部变量不需要@。
5. DECLARE 的顺序要求
在 BEGIN...END 块中,声明顺序必须为:
-
局部变量 (
DECLARE var...) -
条件 (
DECLARE CONDITION...) 和 游标 (DECLARE CURSOR...) -
错误处理程序 (
DECLARE HANDLER...) 顺序错了会报语法错误。可能考判断:"在存储过程中,可以先把游标声明放在变量声明前面"------错。
6. 游标遍历时判断结束
-
常用
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;(02000表示NOT FOUND)。 -
在
FETCH后判断done变量,若为1则退出循环。
7. 触发器中的 NEW 和 OLD
-
INSERT操作:只有NEW(新插入的行),没有OLD。 -
DELETE操作:只有OLD(被删除的行),没有NEW。 -
UPDATE操作:NEW表示更新后的行,OLD表示更新前的行。 -
可以在
BEFORE触发器中修改NEW列的值(如SET NEW.column = ...),AFTER触发器中不能修改。
8. 触发器的触发时机
-
BEFORE:在 INSERT/UPDATE/DELETE 操作之前执行,可用于数据验证或修改。 -
AFTER:在操作之后执行,一般用于日志记录、级联更新等。 -
判断:"触发器可以在 INSERT 操作之前和之后都触发"------对(可以创建多个触发器,但同一表同一时机同一事件只能一个?MySQL 5.7.2+ 允许同一事件有多个触发器,但考试通常认为一个表对同一事件只能有一个触发器,具体看教材)。
9. LEAVE 与 ITERATE 的区别
-
LEAVE相当于break:完全退出循环。 -
ITERATE相当于continue:跳过本次循环剩余语句,进入下一次循环。
10. 自定义错误处理
-
CONTINUE:发生错误后继续执行后续语句(如设置一个标记)。 -
EXIT:发生错误后立即退出当前BEGIN...END块。 -
可以用来捕获重复键、没有数据等错误,避免存储过程崩溃。
四、易混淆对比(重点记忆)
| 对比项 | 说明 |
|---|---|
| 存储过程 vs 存储函数 | 过程无返回值(或用OUT),函数必须有RETURN;调用方式不同 |
IN vs OUT vs INOUT |
IN:只进不出;OUT:只出不进(初始NULL);INOUT:可进可出 |
| 局部变量 vs 用户变量 | 局部用DECLARE,无@,作用域在块内;用户变量以@开头,会话级 |
REPEAT vs WHILE |
REPEAT至少执行一次(先执行后判断);WHILE先判断后执行(可能0次) |
LEAVE vs ITERATE |
LEAVE退出循环;ITERATE跳至下一次循环 |
BEFORE vs AFTER 触发器 |
BEFORE可在修改前校验/修改NEW;AFTER用于操作后记录 |
NEW vs OLD |
INSERT有NEW无OLD;DELETE有OLD无NEW;UPDATE两者都有 |
SHOW PROCEDURE STATUS vs SHOW CREATE PROCEDURE |
前者显示状态信息,后者显示创建语句 |
五、上机实践要点(紧扣期末)
PPT 8.8 节图书管理系统案例覆盖了:
-
存储过程
proc_1:带连接查询和条件判断(IF)。 -
存储过程
proc_2:简单查询。 -
存储函数
func_1:带参数的返回值。 -
存储函数
func_2:带IF和局部变量。 -
触发器
trig_book:AFTER INSERT更新另一张表。 建议手动敲一遍以下核心示例:
sql
-- 1. 存储过程(IN参数)
DELIMITER //
CREATE PROCEDURE GetEmpBySal(IN min_sal DECIMAL(7,2))
BEGIN
SELECT * FROM emp WHERE sal > min_sal;
END //
DELIMITER ;
CALL GetEmpBySal(3000);
-- 2. 存储函数(RETURNS)
DELIMITER //
CREATE FUNCTION GetDeptName(emp_no INT) RETURNS VARCHAR(20)
BEGIN
RETURN (SELECT dname FROM dept d JOIN emp e ON d.deptno = e.deptno WHERE e.empno = emp_no);
END //
DELIMITER ;
SELECT GetDeptName(9839);
-- 3. 触发器(AFTER DELETE)
CREATE TRIGGER backup_del_emp
AFTER DELETE ON emp FOR EACH ROW
INSERT INTO emp_backup VALUES (OLD.empno, OLD.ename, OLD.job, ...);
-- 4. 游标示例(遍历)
DELIMITER //
CREATE PROCEDURE cursor_demo()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_ename VARCHAR(20);
DECLARE cur CURSOR FOR SELECT ename FROM emp;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN cur;
read_loop: LOOP
FETCH cur INTO v_ename;
IF done THEN LEAVE read_loop; END IF;
-- 处理逻辑
END LOOP;
CLOSE cur;
END //
DELIMITER ;
六、自测题(检验掌握程度)
单选题
-
下列哪个参数模式表示参数只能作为输入,不能将修改结果返回给调用者? A.
INB.OUTC.INOUTD.RETURN答案:A -
存储函数中必须包含的语句是: A.
CALLB.RETURNC.OUTD.DECLARE答案:B -
关于局部变量和用户变量,说法正确的是: A. 用户变量必须以
@开头,局部变量不需要 B. 局部变量在整个会话中有效 C. 用户变量只能在存储过程中使用 D. 局部变量不需要DECLARE答案:A -
触发器中,
UPDATE操作可以使用的伪记录是: A. 只有NEWB. 只有OLDC. 既有NEW也有OLDD. 都没有 答案:C -
下列循环语句中,至少执行一次循环体的是: A.
LOOPB.WHILEC.REPEATD. 以上都不对 答案:C(REPEAT 先执行后判断,LOOP 如果不配合 LEAVE 是死循环,但通常说 REPEAT 保证至少一次)
判断题
-
( )存储过程可以没有参数,也可以没有返回值。 对 (存储过程没有
RETURN,返回值通过OUT参数实现,可以没有)。 -
( )在
BEGIN...END块中,错误处理程序的声明可以放在变量声明之前。 错(顺序:变量、条件/游标、错误处理程序)。 -
( )触发器可以调用存储过程。 对 (触发程序中可以包含
CALL语句)。 -
( )
ITERATE语句可以退出当前循环。 错 (ITERATE是跳过本次循环继续下一次,LEAVE才是退出)。 -
( )同一个表上可以创建多个
BEFORE INSERT触发器。 对 (MySQL 5.7.2+ 允许,具体依教材;但传统说法认为只能一个,考试可能以教材为准,建议确认。复习指南中未提,但稳妥认为可以多个,但一个表同一时机同一事件只能一个?此处答案可能因版本而异。建议按教材:MySQL 5.7.2+ 支持多个,但一般考试认为只能一个 。为安全,按常见判断题答案为错,但需看你的教材。根据PPT描述,未明确说可以多个,故可判断为"错")。
简答题(模拟考试)
-
简述存储过程和存储函数的区别。 参考答案:
-
存储过程没有返回值(或通过
OUT参数返回多个值),存储函数必须返回一个值(使用RETURN)。 -
存储过程用
CALL调用,存储函数可以像内置函数一样在表达式中使用(如SELECT func())。 -
存储函数不能包含输出参数(
OUT/INOUT),只能有IN参数。
-
-
写出创建触发器
trig_emp_del的语句,要求:在员工表emp上,当删除一条员工记录时,自动将该员工的ename和deptno插入到日志表emp_log(ename, deptno, del_time)中。sql
CREATE TRIGGER trig_emp_del AFTER DELETE ON emp FOR EACH ROW BEGIN INSERT INTO emp_log(ename, deptno, del_time) VALUES (OLD.ename, OLD.deptno, NOW()); END;
第九
一、本章核心能力目标(考什么?)
-
数据备份 :
mysqldump备份单个/多个/所有数据库的语法,备份文件内容是否包含CREATE DATABASE。 -
数据还原 :
mysql命令(不登录)和source命令(需登录)还原数据。 -
用户管理 :
CREATE USER创建用户(默认只有连接权限),DROP USER删除用户,ALTER USER/SET PASSWORD/mysqladmin修改密码。 -
权限管理 :
GRANT授予权限,REVOKE收回权限,SHOW GRANTS查看权限;权限级别(*.*、db.*、db.table、db.table(col))。 -
root密码丢失恢复 (多学一招):
--skip-grant-tables跳过权限表,FLUSH PRIVILEGES加载权限,再修改密码。
二、必须掌握的核心语法
1. 备份
bash
# 备份单个数据库(不含 CREATE DATABASE 语句)
mysqldump -u用户名 -p密码 数据库名 [表名...] > 备份文件.sql
# 备份多个数据库(含 CREATE DATABASE 语句)
mysqldump -u用户名 -p密码 --databases 数据库1 数据库2 ... > 备份文件.sql
# 备份所有数据库(含 CREATE DATABASE 语句)
mysqldump -u用户名 -p密码 --all-databases > 备份文件.sql
注意 :在操作系统命令行执行,不需要登录 MySQL 。
-p后可直接写密码(无空格)或只写-p回车后输入。
2. 还原
方式一:mysql 命令(不登录 MySQL)
bash
mysql -u用户名 -p密码 [数据库名] < 备份文件.sql
-
如果备份文件中包含
CREATE DATABASE和USE(即使用--databases或--all-databases备份),则不需要指定数据库名。 -
如果备份文件不包含 创建数据库的语句(即备份单个数据库时不带
--databases),则需要先创建数据库,然后在命令中指定该数据库名。
方式二:source 命令(需先登录 MySQL)
sql
USE 数据库名;
SOURCE 备份文件.sql;
3. 用户管理
sql
-- 创建用户(默认只有连接权限 USAGE)
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
-- 删除用户(推荐)
DROP USER '用户名'@'主机名';
-- 修改密码(三种方式)
ALTER USER '用户名'@'主机名' IDENTIFIED BY '新密码'; -- 推荐
SET PASSWORD FOR '用户名'@'主机名' = '新密码'; -- 或 SET PASSWORD = '新密码' 修改当前用户
-- 命令行:mysqladmin -u 用户名 -p password 新密码
4. 权限管理
sql
-- 授予权限
GRANT 权限类型 [(列名列表)] ON 权限级别 TO '用户名'@'主机名' [WITH with_option];
-- 查看权限
SHOW GRANTS FOR '用户名'@'主机名';
-- 收回权限
REVOKE 权限类型 [(列名列表)] ON 权限级别 FROM '用户名'@'主机名';
-- 收回所有权限
REVOKE ALL PRIVILEGES, GRANT OPTION FROM '用户名'@'主机名';
权限级别示例:
-
*.*:所有数据库的所有表(全局) -
bms.*:数据库 bms 的所有表 -
bms.book:数据库 bms 中的 book 表 -
bms.book(name,price):book 表的 name 和 price 列
常用权限 :SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALL PRIVILEGES。
WITH 选项(了解即可):
-
GRANT OPTION:允许用户将自己拥有的权限授予他人。 -
MAX_QUERIES_PER_HOUR等资源限制。
三、老师可能没标但你需掌握的细节(选择题/判断题高频)
1. 备份命令的执行环境
-
mysqldump和mysql(还原)命令是在操作系统命令行 中执行,不是在 MySQL 客户端内部。 -
source命令是在 MySQL 客户端内部执行(先登录)。 -
判断:"使用 mysqldump 备份数据库需要先登录到 MySQL 服务器" ------ 错。
2. 备份文件中是否包含 CREATE DATABASE
| 备份方式 | 是否包含 CREATE DATABASE | 还原时是否需要先创建数据库 |
|---|---|---|
单个数据库(不加 --databases) |
否 | 需要 |
多个数据库(加 --databases) |
是 | 不需要 |
所有数据库(--all-databases) |
是 | 不需要 |
3. 还原时 mysql 命令与 source 的区别
| 命令 | 是否登录MySQL | 是否需指定数据库 | 适用场景 |
|---|---|---|---|
mysql -u... -p... dbname < file.sql |
否 | 若备份文件不含 CREATE DATABASE 则需指定 | 命令行批处理 |
source file.sql |
是(先登录) | 先 USE dbname 或备份文件中含 USE |
交互式客户端内 |
4. CREATE USER 创建的用户默认权限
-
默认只拥有登录(连接)权限 (
USAGE),没有任何数据库对象的操作权限。 -
判断:"用 CREATE USER 创建的用户可以直接查询所有表" ------ 错 ,需要
GRANT授权。
5. DROP USER vs DELETE FROM mysql.user
-
DROP USER会同时删除用户对应的权限记录(从user、db、tables_priv等表中),更彻底。 -
DELETE FROM mysql.user仅删除 user 表记录,还需要FLUSH PRIVILEGES刷新权限,且不会删除其他权限表中的记录,可能留下残留。推荐使用DROP USER。
6. GRANT 语句在 MySQL 8.0 前后的变化
-
MySQL 8.0 之前,
GRANT可以同时创建用户(如果用户不存在)。 -
MySQL 8.0 开始,
GRANT不能 创建用户,必须先用CREATE USER创建,再GRANT。 -
判断:"在 MySQL 8.0 中,可以使用 GRANT 语句创建新用户" ------ 错。
7. 权限的存储位置
-
全局权限:
mysql.user -
数据库权限:
mysql.db -
表权限:
mysql.tables_priv -
列权限:
mysql.columns_priv -
查看用户权限最方便:
SHOW GRANTS
8. FLUSH PRIVILEGES 的用途
-
当直接修改
mysql系统表(如UPDATE mysql.user)后,需要执行FLUSH PRIVILEGES让权限重新加载。 -
使用
GRANT、REVOKE、DROP USER等语句会自动刷新,不需要手动执行。
9. root 密码丢失恢复步骤(简答题可能考)
-
停止 MySQL 服务(
net stop MySQL) -
以
--skip-grant-tables启动 MySQL(跳过权限验证) -
无需密码登录:
mysql -u root -
刷新权限:
FLUSH PRIVILEGES; -
修改密码:
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码'; -
退出,重启 MySQL 服务正常启动。
10. mysqladmin 命令修改密码
-
格式:
mysqladmin -u 用户名 -p password 新密码 -
执行时会提示输入旧密码(
-p后的password是关键字,不是旧密码值)。 -
判断:"mysqladmin 命令可以用来修改任何用户的密码" ------ 对(需要有相应权限)。
四、易混淆对比(重点记忆)
| 对比项 | 说明 |
|---|---|
mysqldump vs mysql |
前者备份,后者还原(也可执行SQL文件)。 |
mysql 命令还原 vs source |
前者无需登录,后者需登录;前者适合脚本,后者适合交互。 |
CREATE USER vs GRANT(8.0前后) |
8.0前 GRANT 可创建用户,8.0后必须分开。 |
DROP USER vs DELETE FROM mysql.user |
DROP USER 彻底;DELETE 仅删 user 表需 FLUSH。 |
备份单个数据库(不加--databases) vs 加--databases |
前者不含 CREATE DATABASE,后者包含。 |
GRANT 的权限级别 |
*.* 全局,db.* 数据库级,db.table 表级,db.table(col) 列级。 |
REVOKE 收回列权限 vs 表权限 |
列权限需指定列名,表权限不指定列。 |
USAGE 权限 |
表示无任何实际权限,但可以连接。 |
五、上机实践要点(紧扣期末)
PPT 9.4 节图书管理系统案例:
-
备份
bms数据库到bms_20210528.sql(使用mysqldump) -
创建用户
user2@localhost,密码user2pw -
授予
INSERT, UPDATE, SELECT权限在bms.*
建议亲手操作以下核心命令(在命令行和 MySQL 内分别尝试):
bash
# 1. 备份单个数据库(不含CREATE DATABASE)
mysqldump -uroot -p bms > D:/backup/bms_backup.sql
# 2. 还原:先创建数据库,再导入
mysql -uroot -p -e "CREATE DATABASE bms_restore;"
mysql -uroot -p bms_restore < D:/backup/bms_backup.sql
# 3. 备份多个数据库(含CREATE DATABASE)
mysqldump -uroot -p --databases bms mysql > D:/backup/bms_mysql.sql
# 还原时不需要指定数据库
mysql -uroot -p < D:/backup/bms_mysql.sql
# 4. 创建用户并授权(在MySQL内)
CREATE USER 'reader'@'localhost' IDENTIFIED BY 'read123';
GRANT SELECT ON bms.* TO 'reader'@'localhost';
SHOW GRANTS FOR 'reader'@'localhost';
# 5. 测试权限(新开命令行登录reader用户)
mysql -ureader -p read123
# 尝试 SELECT, INSERT 验证
# 6. 收回权限
REVOKE SELECT ON bms.* FROM 'reader'@'localhost';
DROP USER 'reader'@'localhost';
六、自测题(检验掌握程度)
单选题
-
下列哪个命令用于备份 MySQL 数据库? A.
mysqlB.mysqldumpC.sourceD.backup答案:B -
使用
mysqldump备份单个数据库(不加--databases),备份文件中是否包含CREATE DATABASE语句? A. 包含 B. 不包含 C. 取决于版本 D. 包含但被注释 答案:B -
还原数据时,需要先登录 MySQL 的命令是: A.
mysql < file.sqlB.source file.sqlC.mysqldump < file.sqlD.mysqladmin restore答案:B -
创建一个新用户,默认拥有什么权限? A. 所有权限 B. 查询权限 C. 连接权限 D. 没有权限 答案:C (
USAGE) -
授予用户
test对数据库mydb中所有表的查询权限,正确的语句是: A.GRANT SELECT ON mydb TO 'test'@'localhost';B.GRANT SELECT ON mydb.* TO 'test'@'localhost';C.GRANT SELECT ON *.* TO 'test'@'localhost';D.GRANT SELECT ON mydb.table TO 'test'@'localhost';答案:B
判断题
-
( )
mysqldump命令可以在 MySQL 客户端内执行。 错(需在操作系统命令行执行) -
( )使用
mysql命令还原数据时,如果备份文件中包含CREATE DATABASE语句,则不需要指定数据库名。 对(因为备份文件会创建数据库并选择它) -
( )
DROP USER删除用户后,该用户创建的表也会被自动删除。 错(表还在,只是用户无法访问;表属于数据库,不属于用户) -
( )
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost'授予了该用户所有数据库的所有权限,包括GRANT OPTION。 错 (ALL PRIVILEGES不包括GRANT OPTION,如果需要还需单独加WITH GRANT OPTION) -
( )MySQL 8.0 中,可以使用
GRANT语句创建新用户。 错 (必须先CREATE USER)
简答题(模拟考试)
-
请简述
mysqldump备份单个数据库和备份多个数据库在语法上的区别,以及还原时的不同处理。 参考答案:-
备份单个数据库:
mysqldump -u root -p 数据库名 > 文件.sql,备份文件中不包含CREATE DATABASE语句,还原时需要先创建数据库,然后用mysql -u root -p 数据库名 < 文件.sql。 -
备份多个数据库:
mysqldump -u root -p --databases 数据库1 数据库2 > 文件.sql,备份文件中包含CREATE DATABASE和USE语句,还原时直接mysql -u root -p < 文件.sql即可,无需指定数据库。
-
-
写出收回用户
user1@localhost在数据库school的表student上的INSERT权限,以及收回该用户所有权限的 SQL 语句。sql
-- 收回指定权限 REVOKE INSERT ON school.student FROM 'user1'@'localhost'; -- 收回所有权限 REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user1'@'localhost'; -
简述 root 用户密码丢失的恢复步骤(至少4步)。 参考答案:
-
停止 MySQL 服务(
net stop MySQL); -
以
--skip-grant-tables选项启动 MySQL(跳过权限验证); -
无需密码登录 MySQL(
mysql -u root); -
刷新权限表(
FLUSH PRIVILEGES;); -
使用
ALTER USER语句重新设置 root 密码; -
退出,重启 MySQL 服务正常启动。
-
第三
一、本章核心能力目标(考什么?)
-
插入数据 :
INSERT INTO ... VALUES一次插入单条或多条;INSERT INTO ... SET方式;插入时字段与值的对应关系;非空约束的影响。 -
更新数据 :
UPDATE ... SET配合WHERE更新部分行,不带WHERE会更新全表;可使用表达式(如sal = sal + 200)。 -
删除数据 :
DELETE FROM ... WHERE删除部分行;不带WHERE删除全表;TRUNCATE TABLE删除全表并重置自增。 -
DELETE与TRUNCATE的区别(简答/选择高频,4点)。
二、必须掌握的核心语法
1. 插入数据
sql
-- 方式1:指定字段(推荐,避免出错)
INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1, 值2, ...);
-- 方式2:省略字段名(必须为所有字段按顺序提供值)
INSERT INTO 表名 VALUES (值1, 值2, ...);
-- 方式3:使用 SET 子句(一次只能插入一条)
INSERT INTO 表名 SET 字段1 = 值1, 字段2 = 值2, ...;
-- 一次插入多条(用逗号分隔多条 VALUES)
INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1, 值2, ...), (值1, 值2, ...), ...;
注意 :
VALUE和VALUES通用,但标准是VALUES。
2. 更新数据
sql
-- 更新符合条件的行
UPDATE 表名 SET 字段1 = 新值1, 字段2 = 新值2, ... WHERE 条件;
-- 不带 WHERE:更新所有行
UPDATE 表名 SET 字段1 = 新值1;
3. 删除数据
sql
-- 删除符合条件的行
DELETE FROM 表名 WHERE 条件;
-- 删除所有行(保留表结构)
DELETE FROM 表名;
-- 快速清空表并重置自增
TRUNCATE TABLE 表名;
三、老师可能没标但你需掌握的细节(选择题/判断题高频)
1. INSERT 省略字段名时的严格要求
-
必须为表中每一个字段提供值,且值的顺序必须与表定义时的字段顺序一致。
-
如果某个字段有默认值或允许
NULL,也必须在VALUES中占位(可以写DEFAULT或NULL)。 -
判断:"
INSERT INTO 表名 VALUES (值1, 值2)可以只给部分字段赋值" ------ 错。
2. 非空约束与默认值的关系
-
如果字段定义了
NOT NULL且没有DEFAULT,插入时必须显式赋值。 -
如果字段定义了
NOT NULL但有DEFAULT,则可以省略该字段(会使用默认值)。 -
示例错误:插入时省略
NOT NULL且无默认值的字段 → 报错。
3. UPDATE 不带 WHERE 的危险性
-
不带
WHERE会更新表中所有行,造成全表修改。 -
考试可能考:"
UPDATE emp SET sal = sal * 1.1;会将所有员工涨薪10%" ------ 对。
4. DELETE 与 TRUNCATE 的 4 点核心区别(简答必背)
| 对比项 | DELETE |
TRUNCATE |
|---|---|---|
| 语句类型 | 数据操纵语言(DML) | 数据定义语言(DDL) |
是否可带 WHERE |
可以,删除部分行 | 不可以,只能删除全部行 |
| 删除方式 | 逐行删除(速度慢,可触发触发器) | 删除表后重建(速度快,不触发触发器) |
| 自增字段(AUTO_INCREMENT) | 不重置,下次插入从上次最大值+1开始 | 重置为 1 |
注意 :
TRUNCATE后,自增字段从 1 开始;DELETE全表后,自增字段从之前最大值+1 开始(除非重启服务器或执行ALTER TABLE ... AUTO_INCREMENT=1)。
5. TRUNCATE 的其他特点
-
不能回滚(在事务中,
DELETE可以回滚,TRUNCATE通常不可回滚,取决于存储引擎和事务隔离,但一般认为不可回滚)。 -
会释放表占用的存储空间(
DELETE不释放,只是标记删除)。 -
执行
TRUNCATE后,表结构、索引等保持不变。
6. INSERT 中使用表达式和函数
-
可以插入当前时间:
CURRENT_TIMESTAMP或NOW()。 -
可以进行计算:
VALUES(1+2, 3*4)。 -
上机实践中用了
CURRENT_TIMESTAMP。
7. UPDATE 中使用表达式
-
如
sal = sal + 200,price = price * 0.9。 -
可以同时更新多个字段。
8. DELETE 和 TRUNCATE 的权限
- 都需要
DELETE或DROP权限(TRUNCATE通常需要DROP权限)。
9. 插入多行时,如果某行出错
- 在默认配置下,如果一行数据违反约束(如重复主键),整个
INSERT语句会失败,所有行都不插入(原子性)。但可以设置IGNORE或ON DUPLICATE KEY UPDATE,不过考试不深入。
10. INSERT ... SET 的适用场景
-
适合插入单条记录,语法更清晰(不需要关注字段顺序)。
-
一次只能插一条。
四、易混淆对比(重点记忆)
| 对比项 | 说明 |
|---|---|
INSERT 指定字段 vs 省略字段 |
指定字段更安全,顺序可调;省略字段必须按表定义顺序提供所有值 |
DELETE 全表 vs TRUNCATE |
DELETE 是 DML、可回滚、不重置自增、慢;TRUNCATE 是 DDL、不可回滚、重置自增、快 |
DELETE 带 WHERE vs 不带 |
不带会删除所有行,危险 |
UPDATE 带 WHERE vs 不带 |
不带会更新所有行 |
VALUE vs VALUES |
在 MySQL 中通用,但标准是 VALUES |
CURRENT_TIMESTAMP vs NOW() |
两者几乎等效,都返回当前日期时间 |
五、上机实践要点(紧扣期末)
PPT 3.4 节图书管理系统案例覆盖了:
-
插入单条/多条图书信息(使用
CURRENT_TIMESTAMP)。 -
插入用户信息。
-
更新单条(修改状态、价格)和批量(所有价格下调 10%)。
-
删除图书(
DELETE)。 -
借阅操作(
UPDATE多个字段:borrower_id,borrow_time,state)。
建议亲手敲一遍以下核心语句:
sql
-- 1. 插入单条(指定字段)
INSERT INTO emp (empno, ename, job, sal, deptno) VALUES (1001, '测试', '职员', 3000, 10);
-- 2. 插入多条
INSERT INTO emp (empno, ename, job, sal, deptno) VALUES
(1002, '张三', '职员', 3200, 20),
(1003, '李四', '经理', 5000, 20);
-- 3. 使用 SET 插入
INSERT INTO emp SET empno=1004, ename='王五', job='保洁', sal=2500, deptno=30;
-- 4. 更新:涨薪200(带条件)
UPDATE emp SET sal = sal + 200 WHERE ename = '张三';
-- 5. 更新:全表涨薪(不带条件,危险,测试前备份)
UPDATE emp SET sal = sal * 1.05;
-- 6. 删除:指定条件
DELETE FROM emp WHERE empno = 1004;
-- 7. 清空表(重置自增)
TRUNCATE TABLE emp_copy;
-- 8. 验证自增区别
CREATE TABLE test_auto (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(10));
INSERT INTO test_auto (name) VALUES ('a'),('b'),('c');
DELETE FROM test_auto; -- 或 TRUNCATE
INSERT INTO test_auto (name) VALUES ('d');
SELECT * FROM test_auto; -- DELETE 后 id=4,TRUNCATE 后 id=1
六、自测题(检验掌握程度)
单选题
-
向表
student中所有字段插入数据,正确的写法是: A.INSERT INTO student VALUES (101, '张三');B.INSERT INTO student (id, name) VALUES (101, '张三');C.INSERT INTO student SET id=101, name='张三';D. 以上都是正确的 答案:D(三种方式都正确,但 A 要求表只有两个字段且顺序匹配) -
下列哪个语句会将表中所有员工的工资增加 100 元? A.
UPDATE emp SET sal = sal + 100 WHERE 1=1;B.UPDATE emp SET sal = sal + 100;C.UPDATE emp SET sal + 100;D. A 和 B 都正确 答案:D (A 中WHERE 1=1条件恒真,等同于全表) -
关于
DELETE和TRUNCATE,说法正确的是: A.DELETE可以带WHERE,TRUNCATE也可以 B.TRUNCATE会重置自增字段,DELETE不会 C.DELETE比TRUNCATE执行速度快 D.TRUNCATE是 DML 语句 答案:B -
假设表
t有自增主键id,执行DELETE FROM t;后插入新数据,新记录的id是: A. 1 B. 删除前最大 id+1 C. 随机 D. 0 答案:B
判断题
-
( )
INSERT INTO 表名 VALUES (值1, 值2)要求表必须有且仅有两个字段。 错(如果表有三个字段但后两个有默认值或允许 NULL,也可以,但一般不这么用;严格来说,必须为每个字段提供值,顺序一致。最好理解为"必须为所有字段提供值") -
( )
UPDATE语句如果不带WHERE子句,则会更新表中所有记录。 对 -
( )
TRUNCATE语句可以回滚。 错(通常不可回滚,属于 DDL) -
( )使用
INSERT INTO ... SET可以一次插入多条记录。 错(只能插入一条)
简答题(模拟考试)
-
请列出
DELETE和TRUNCATE的至少 3 点区别。 参考答案 : ①DELETE是 DML,可以带WHERE删除部分行;TRUNCATE是 DDL,只能删除全部行。 ②DELETE逐行删除,速度慢,会触发触发器;TRUNCATE删除表后重建,速度快,不触发触发器。 ③DELETE删除全表后,自增字段从之前最大值+1 开始;TRUNCATE会重置自增字段为 1。 ④DELETE可以回滚(事务中),TRUNCATE不可回滚。 -
写出将员工表
emp中部门编号为30的所有员工工资更新为原来的 1.1 倍,并删除职位为'保洁'的员工的 SQL 语句。sql
UPDATE emp SET sal = sal * 1.1 WHERE deptno = 30; DELETE FROM emp WHERE job = '保洁';
第七
一、本章核心能力目标(考什么?)
-
插入数据 :
INSERT的三种写法(指定字段、省略字段、SET子句);一次插入单条 vs 多条;非空约束与默认值的影响。 -
更新数据 :
UPDATE带WHERE更新部分行;不带WHERE会全表更新;可使用表达式(如sal = sal + 200)。 -
删除数据 :
DELETE带WHERE删除部分行;不带WHERE删除全表;TRUNCATE清空表并重置自增。 -
DELETE与TRUNCATE的区别(简答题高频,4点)。
二、必须掌握的核心语法
1. 插入数据
sql
-- 方式1:指定字段(推荐)
INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1, 值2, ...);
-- 方式2:省略字段(必须按表定义顺序为所有字段提供值)
INSERT INTO 表名 VALUES (值1, 值2, ...);
-- 方式3:使用 SET 子句(一次一条)
INSERT INTO 表名 SET 字段1 = 值1, 字段2 = 值2, ...;
-- 一次插入多条(用逗号分隔多个 VALUES)
INSERT INTO 表名 (字段1, 字段2, ...) VALUES
(值1, 值2, ...),
(值1, 值2, ...),
...;
注意:
VALUE和VALUES在 MySQL 中通用,但标准写法是VALUES。
2. 更新数据
sql
-- 带条件更新
UPDATE 表名 SET 字段1 = 新值1, 字段2 = 新值2, ... WHERE 条件;
-- 不带条件(更新所有行,危险)
UPDATE 表名 SET 字段1 = 新值1;
3. 删除数据
sql
-- 带条件删除
DELETE FROM 表名 WHERE 条件;
-- 删除所有行(保留表结构)
DELETE FROM 表名;
-- 快速清空并重置自增
TRUNCATE [TABLE] 表名;
三、老师可能没标但你需掌握的细节(选择题/判断题高频)
1. INSERT 省略字段名的严格要求
-
必须为表中每一个字段按定义顺序提供值,且值的个数、类型必须匹配。
-
如果某个字段有默认值或允许
NULL,也必须在VALUES中显式写DEFAULT或NULL(或直接写值)。 -
判断:"
INSERT INTO 表名 VALUES (值1, 值2)可以只给部分字段赋值" ------ 错。
2. 非空约束与默认值的影响
-
字段定义了
NOT NULL且无DEFAULT时,插入必须显式赋值,否则报错。 -
字段有
DEFAULT值时,插入时可以省略该字段(使用默认值)。 -
示例错误:
INSERT INTO emp (empno) VALUES (100);如果ename是NOT NULL无默认值,会报错。
3. UPDATE 不带 WHERE 会更新全表
- 这是一个常见危险操作,考试常考:"
UPDATE emp SET sal = sal * 1.1;会将所有员工涨薪10%" ------ 对。
4. DELETE 与 TRUNCATE 的核心区别(简答题必背)
| 对比项 | DELETE |
TRUNCATE |
|---|---|---|
| 语句类型 | 数据操纵语言(DML) | 数据定义语言(DDL) |
是否可带 WHERE |
可以,删除部分行 | 不可以,只能删除全部行 |
| 删除方式 | 逐行删除(慢,可触发触发器) | 删除表后重建(快,不触发触发器) |
| 自增字段(AUTO_INCREMENT) | 不重置,下次插入从上次最大值+1开始 | 重置为 1 |
| 事务回滚 | 可以回滚(InnoDB) | 不可回滚(DDL) |
| 磁盘空间 | 不释放,只是标记删除 | 释放表空间 |
考试中常考第4点(自增字段)和第1点(语句类型)。
5. TRUNCATE 的其他特点
-
执行后,表结构、索引、约束等保持不变。
-
需要
DROP权限(DELETE只需要DELETE权限)。 -
不能用于有外键约束引用的表(除非级联)。
6. INSERT 中使用函数和表达式
-
可以插入当前时间:
CURRENT_TIMESTAMP、NOW()。 -
可以进行计算:
VALUES(1+2, 3*4)。 -
上机实践中用了
CURRENT_TIMESTAMP。
7. UPDATE 中使用表达式
-
如
sal = sal + 200,price = price * 0.9。 -
可同时更新多个字段,如
SET a=1, b=2。
8. 插入多行时某行出错的影响
- 默认情况下,如果某行违反约束(如重复主键),整个
INSERT语句会失败,所有行都不插入(原子性)。但如果使用INSERT IGNORE,则忽略出错行继续插入其他行(不要求掌握,了解即可)。
9. INSERT ... SET 的适用场景
- 语法清晰,不需要记住字段顺序,但一次只能插入一条记录。
10. DELETE 全表 vs TRUNCATE 的实际使用建议
- 要快速清空表且重置自增,用
TRUNCATE;要保留自增序列或需要回滚,用DELETE(但DELETE全表很慢)。
四、易混淆对比(重点记忆)
| 对比项 | 说明 |
|---|---|
INSERT 指定字段 vs 省略字段 |
指定字段安全、顺序自由;省略字段必须全字段且顺序固定 |
DELETE 全表 vs TRUNCATE |
DELETE 是 DML、可回滚、不重置自增、慢;TRUNCATE 是 DDL、不可回滚、重置自增、快 |
DELETE 带 WHERE vs 不带 |
不带会删除所有行 |
UPDATE 带 WHERE vs 不带 |
不带会更新所有行 |
VALUE vs VALUES |
在 MySQL 中通用,但标准是 VALUES |
CURRENT_TIMESTAMP vs NOW() |
效果相同,都返回当前日期时间 |
五、上机实践要点(紧扣期末)
PPT 3.4 节图书管理系统案例覆盖了:
-
插入单条图书信息(使用
CURRENT_TIMESTAMP)。 -
插入多条用户信息。
-
批量插入图书。
-
更新单条(修改状态、价格)和批量(所有价格下调10%)。
-
删除图书(
DELETE)。 -
借阅操作(
UPDATE多个字段)。
建议亲手敲一遍以下核心语句:
sql
-- 1. 插入单条(指定字段)
INSERT INTO emp (empno, ename, job, sal, deptno) VALUES (1001, '测试', '职员', 3000, 10);
-- 2. 插入多条
INSERT INTO emp (empno, ename, job, sal, deptno) VALUES
(1002, '张三', '职员', 3200, 20),
(1003, '李四', '经理', 5000, 20);
-- 3. 使用 SET 插入
INSERT INTO emp SET empno=1004, ename='王五', job='保洁', sal=2500, deptno=30;
-- 4. 更新:涨薪200(带条件)
UPDATE emp SET sal = sal + 200 WHERE ename = '张三';
-- 5. 更新:全表涨薪(危险,测试前备份)
UPDATE emp SET sal = sal * 1.05;
-- 6. 删除:指定条件
DELETE FROM emp WHERE empno = 1004;
-- 7. 清空表(重置自增)
TRUNCATE TABLE emp_copy;
-- 8. 验证自增区别
CREATE TABLE test_auto (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(10));
INSERT INTO test_auto (name) VALUES ('a'),('b'),('c');
DELETE FROM test_auto; -- 或 TRUNCATE test_auto
INSERT INTO test_auto (name) VALUES ('d');
SELECT * FROM test_auto; -- DELETE 后 id=4,TRUNCATE 后 id=1
六、自测题(检验掌握程度)
单选题
-
向表
student中所有字段插入数据,正确的写法是: A.INSERT INTO student VALUES (101, '张三');B.INSERT INTO student (id, name) VALUES (101, '张三');C.INSERT INTO student SET id=101, name='张三';D. 以上都正确 答案:D(A要求表正好有两个字段且顺序匹配,但通常题目认为都对) -
下列哪个语句会将表中所有员工的工资增加 100 元? A.
UPDATE emp SET sal = sal + 100 WHERE 1=1;B.UPDATE emp SET sal = sal + 100;C.UPDATE emp SET sal + 100;D. A 和 B 都正确 答案:D -
关于
DELETE和TRUNCATE,说法正确的是: A.DELETE可以带WHERE,TRUNCATE也可以 B.TRUNCATE会重置自增字段,DELETE不会 C.DELETE比TRUNCATE执行速度快 D.TRUNCATE是 DML 语句 答案:B -
假设表
t有自增主键id,执行DELETE FROM t;后插入新数据,新记录的id是: A. 1 B. 删除前最大 id+1 C. 随机 D. 0 答案:B
判断题
-
( )
INSERT INTO 表名 VALUES (值1, 值2)要求表必须有且仅有两个字段。 错(如果表有三个字段但后两个有默认值或允许 NULL,也可以,但一般不这么用;严格来说,必须为所有字段提供值。最好判断为错) -
( )
UPDATE语句如果不带WHERE子句,则会更新表中所有记录。 对 -
( )
TRUNCATE语句可以回滚。 错(通常不可回滚) -
( )使用
INSERT INTO ... SET可以一次插入多条记录。 错(只能一条)
简答题(模拟考试)
-
请列出
DELETE和TRUNCATE的至少 3 点区别。 参考答案 : ①DELETE是 DML,可以带WHERE删除部分行;TRUNCATE是 DDL,只能删除全部行。 ②DELETE逐行删除,速度慢,会触发触发器;TRUNCATE删除表后重建,速度快,不触发触发器。 ③DELETE删除全表后,自增字段从之前最大值+1 开始;TRUNCATE会重置自增字段为 1。 ④DELETE可以回滚(事务中),TRUNCATE不可回滚。 -
写出将员工表
emp中部门编号为30的所有员工工资更新为原来的 1.1 倍,并删除职位为'保洁'的员工的 SQL 语句。sql
UPDATE emp SET sal = sal * 1.1 WHERE deptno = 30; DELETE FROM emp WHERE job = '保洁';