07-错误处理选项
-f, --force 强制执行SQL
-v, --verbose 显示更多信息
--show-warnings 显示警告信息
在一个批量执行的SQL中,如果有其中一个SQL执行出错,正常情况下,该批处理将停止退出。加上-f 选项,则跳过出错 SQL,强制执行后面的 SQL;加上-v 选项,则显示出错的SQL语句;加上--show-warnings,则会显示全部错误信息。
这3个参数经常一起使用,在很多情况下会对用户很有帮助,比如加载数据。如果数据中有语法错误的地方,则会将出错信息记录在日志中,而不会停止使得后面的正常 SQL 无法执行;而出错的语句,也可以在日志中得以查看,进行修复。下面是一个例子。
(1)设置测试SQL文本a.sql和测试表t2,a.sql中记录了3条insert语句,t2为只有一个int类型字段的空表。
[zzx@localhost~]$ more a.sql
insert into t2 values(1);
insert into t2 values(2a);
insert into t2 values(3);
mysql> desc t2;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> select * from t2;
Empty set (0.00 sec)
(2)不加任何参数将数据导入表t2。
[zzx@localhost~]$ mysql -uroot test < a.sql
ERROR 1054 (42S22) at line 2: Unknown column '2a' in 'field list'
可以发现,在导入过程中出错。查看一下实际导入的记录:
[zzx@localhost~]$ mysql -uroot test -e 'select * from t2'
+------+
| id |
+------+
| 1 |
+------+
可以发现,由于第二条记录出现语法错误,无法插入表t2,系统自动退出,第一条记录成功插入,第三条记录没有插入。
(3)加参数-f重新导入。
[zzx@localhost~]$ mysql -uroot test -f < a.sql
ERROR 1054 (42S22) at line 2: Unknown column '2a' in 'field list'
[zzx@localhost~]$ mysql -uroot test -e 'select * from t2'
+------+
| id |
+------+
| 1 |
| 1 |
| 3 |
+------+
可以发现,虽然导入过程依旧报错,但是出错后的记录3却已经成功插入。但是我们只能看到部分出错信息,无法定位出错的SQL语句。
(4)加参数-v后重新导入。
[zzx@localhost~]$ mysql -uroot test -f -v< a.sql
insert into t2 values(1)
insert into t2 values(2a)
ERROR 1054 (42S22) at line 2: Unknown column '2a' in 'field list'
insert into t2 values(3)
[zzx@localhost~]$ mysql -uroot test -e 'select * from t2'
+------+
| id |
+------+
| 1 |
| 1 |
| 3 |
| 1 |
| 3 |
+------+
这时发现,出错后的SQL依然能正确插入,并且对出错SQL和错误内容都进行了提示,我们可以很容易地定位并解决问题。
(5)修改测试数据,将第二条记录中的“2a”改为“2222222222222222222”,显然,后者超出了int数据类型的范围。
[zzx@localhost~]$ more a.sql
insert into t2 values(1);
insert into t2 values(2222222222222222222);
insert into t2 values(3);
(6)再次将a.sql导入表t2:
[zzx@localhost~]$ mysql -uroot test < a.sql
这次没有出现任何错误提示,此时没有设置 SQL_MODE,默认是非严格的数据校验,也就是第二条记录虽然可以插入表t2,但是插入的数据是错误的。我们看一下t2的数据:
mysql> select * from t2;
+------------+
| id |
+------------+
|1|
| 2147483647 |
|3|
+------------+
3 rows in set (0.00 sec
果然,插入的数据是int类型的最大值“2147483647”,而非“2222222222222222222”。
但是由于只是警告,并没有停止出错 SQL 的运行,这样会导致插入错误的数据,而我们却无法得知。所以下面尝试加入-v参数再次导入。
(7)加-v参数,再次导入t2。
[zzx@localhost~]$ mysql -uroot -v test < a.sql
insert into t2 values(1)
insert into t2 values(2222222222222222222)
insert into t2 values(3)
结果显示了所有 SQL 语句的执行情况,但是对第二条出错语句并没有任何报警提示,我们仍然无法得知数据出错。最后加上--show-warnings选项试试。
(8)加上--show-warnings选项再次导入表t2。
[zzx@localhost~]$ mysql -uroot -v --show-warnings test < a.sql
insert into t2 values(1)
insert into t2 values(2222222222222222222)
Warning (Code 1264): Out of range value adjusted for column 'id' at row 1
insert into t2 values(3)
结果发现,第二条错误数据报警,提示插入的值超出了字段的范围,可以从这个日志中很容易地找到错误数据。
通过上面的测试例子,可以发现-f、-v、--show-warnings 选项在执行一些可能含有语法错误或者数据错误的批处理作业中,可以记录比较完整的日志,从而帮助用户发现并解决这些错误。