批处理模式
导学
前面所有示例都是在 mysql> 提示符下交互式地逐条输入 SQL。但在实际工作中,你更常遇到这样的场景:课程作业要求提交一段完整的建表+插数据+查询脚本;或者每天凌晨需要自动执行一组统计 SQL。这些场景都需要批处理模式——把 SQL 语句预先写入文件,然后一次性交给 MySQL 执行。
定义
批处理模式(Batch Mode):将一条或多条 SQL 语句保存在文本文件中,通过命令行重定向或 source 命令,让 mysql 客户端一次性读取并执行,无需人工逐条输入。
前置准备:创建测试脚本
先准备一个名为 demo.sql 的脚本文件,内容如下:
-- demo.sql:建库、建表、插数据、查询
CREATE DATABASE IF NOT EXISTS batch_demo
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
USE batch_demo;
CREATE TABLE IF NOT EXISTS employees (
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(20) NOT NULL,
dept VARCHAR(20) DEFAULT '技术部',
score DECIMAL(5,2)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);
SELECT emp_name, score FROM employees;
脚本中
--开头的行是注释,MySQL 执行时会忽略。
场景一:命令行重定向执行(最常用)
当前数据状态:服务器上尚无 batch_demo 数据库。
操作语句:在终端执行:
mysql -u root -p < demo.sql
输入密码后,MySQL 会逐行读取 demo.sql 并执行。
操作后的数据状态:
emp_name score
大翔 100.00
白歌 NULL
结果解读:
mysql -u root -p < demo.sql中,<是 Shell 输入重定向,将文件内容作为mysql的标准输入- 批处理模式下,查询结果以纯文本格式输出(无表格边框),列之间用 Tab 分隔
- 如果脚本中有
USE batch_demo;,后续语句会自动在该库中执行
场景二:输出重定向到文件
当前数据状态:demo.sql 已执行完毕,batch_demo 库已存在。
操作语句:
mysql -u root -p < demo.sql > result.txt 2> error.log
操作后的数据状态:
查看 result.txt:
emp_name score
大翔 100.00
白歌 NULL
查看 error.log:
- 如果脚本执行无错误,该文件为空
- 如果有语法错误,错误信息会写入此处
结果解读:
> result.txt将标准输出(查询结果)重定向到文件2> error.log将标准错误(报错信息)重定向到另一个文件- 这是自动化任务和课程作业提交的标准做法:结果和错误分离,便于排查
场景三:在 mysql 提示符内执行脚本(source 命令)
当前数据状态:已连接到 MySQL 服务器,当前在 batch_demo 库中。
操作语句:
-- 在 mysql> 提示符下执行
source demo.sql;
-- 或简写
\. demo.sql;
操作后的数据状态:
Database changed
Query OK, 0 rows affected
...
emp_name score
大翔 100.00
白歌 NULL
结果解读:
source和\.完全等价,都是在已连接的会话中读取并执行外部脚本- 与命令行重定向的区别:
source在当前会话中执行,可以保留会话变量和事务状态;命令行重定向是新开一个 mysql 进程 - 如果脚本路径包含空格,需要用引号包裹:
source '/path/with spaces/demo.sql';
场景四:获得交互式表格输出(-t 选项)
当前数据状态:batch_demo 库已存在。
操作语句:
mysql -u root -p -t < demo.sql
操作后的数据状态:
+----------+--------+
| emp_name | score |
+----------+--------+
| 大翔 | 100.00 |
| 白歌 | NULL |
+----------+--------+
结果解读:
- 批处理模式默认输出纯文本(无表格线),适合程序解析
-t(--table)选项强制输出交互式的表格格式,方便人工阅读- 课程作业演示或调试脚本时,
-t是常用选项
场景五:回显执行的语句(-v 选项)
当前数据状态:batch_demo 库已存在。
操作语句:
mysql -u root -p -v < demo.sql
操作后的数据状态(节选):
CREATE DATABASE IF NOT EXISTS batch_demo DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci
USE batch_demo
CREATE TABLE IF NOT EXISTS employees (...) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
INSERT INTO employees (emp_name, dept, score) VALUES ('大翔', '技术部', 100), ('白歌', '技术部', NULL)
SELECT emp_name, score FROM employees
emp_name score
大翔 100.00
白歌 NULL
结果解读:
-v(--verbose)会在结果前回显每一条执行的 SQL 语句- 调试脚本时非常有用:可以清楚看到哪条语句产生了哪段输出
-v和-t可以组合使用:mysql -u root -p -v -t < demo.sql
场景六:出错时继续执行(--force 选项)
当前数据状态:batch_demo 库已存在。
准备一个故意包含错误的脚本 bad.sql:
USE batch_demo;
SELECT * FROM employees;
SELECT * FROM not_exist_table; -- 错误:表不存在
SELECT emp_name FROM employees; -- 这条应该继续执行
操作语句:
# 不加 --force,遇到错误会中断
mysql -u root -p < bad.sql
# 加 --force,遇到错误继续执行后续语句
mysql -u root -p --force < bad.sql
操作后的数据状态(加 --force 时):
emp_id emp_name dept score
1 大翔 技术部 100.00
2 白歌 技术部 NULL
ERROR 1146 (42S02) at line 3: Table 'batch_demo.not_exist_table' doesn't exist
emp_name
大翔
白歌
结果解读:
- 默认情况下,脚本中任何一条语句报错,mysql 会立即退出,后续语句不再执行
--force(-f)选项让 mysql 忽略错误继续执行- 适用场景:初始化脚本中某些
DROP TABLE IF EXISTS可能因表不存在而报错,但不影响后续建表
常见误区
| 误区 | 正解 |
|---|---|
| "批处理模式只能执行查询" | 可以执行任何 SQL:DDL(CREATE/DROP)、DML(INSERT/UPDATE)、DCL(GRANT)均可。 |
source 和命令行重定向完全一样 | 不一样。source 在当前会话执行,保留事务和变量;< 是新建进程执行。 |
| 批处理模式输出格式和交互式相同 | 默认不同。批处理是纯文本,交互式是表格。用 -t 可统一。 |
脚本中不需要写 USE | 如果不写 USE,所有操作都在连接时默认的数据库中执行。建议脚本开头显式写 USE。 |
面试考点
Q:批处理模式和交互模式有什么区别?
交互模式逐条输入、即时查看结果;批处理模式将 SQL 写入文件后一次性执行。批处理默认输出纯文本格式,适合自动化和重定向。
Q:mysql < script.sql 和 mysql> source script.sql 有什么区别?
mysql < script.sql是 Shell 重定向,会新开一个 mysql 进程执行;source script.sql是在当前已连接的 mysql 会话中执行,可以保留会话变量和事务上下文。
Q:如何让批处理模式的输出也显示表格边框?
加
-t(--table)选项:mysql -u root -p -t < script.sql。
Q:脚本中某条语句报错,如何不让整个脚本中断?
加
--force(-f)选项:mysql -u root -p --force < script.sql。
小结
- 批处理模式通过
mysql < file.sql或source file.sql执行脚本文件 >可将结果重定向到文件,2>可将错误重定向到文件-t获得表格输出,-v回显执行的语句,--force忽略错误继续执行- 脚本开头建议显式写
USE 数据库名;,避免操作到错误的库
清理测试数据:
DROP DATABASE IF EXISTS batch_demo;
下一章引子:学会了在命令行操作 MySQL,接下来看看 MySQL 支持哪些数据类型,以及如何为表选择最合适的类型。