首页 > 数据库 > MySQL > MySQL的update语句避坑
mysql> drop table if exists t1;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE `t1` (
-> `id` int(11) DEFAULT NULL,
-> `c1` int(11) DEFAULT NULL,
-> `c2` varchar(16) DEFAULT NULL
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected, 2 warnings (0.02 sec)
mysql> insert into t1 values (1,1,'A'),(2,2,'B'),(3,3,'C');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from t1;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 1 | A |
| 2 | 2 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)
正常的update语句,set部分用逗号分隔:
mysql> update t1 set c1=11,c2='AA' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from t1;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 11 | AA |
| 2 | 2 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)
set部分用and连接,轻则造成报错,重则得到意料之外的数据!
mysql> update t1 set c2='BB' and c1= 22 where id=2;
ERROR 1292 (22007): Truncated incorrect DOUBLE value: 'BB'
mysql> update t1 set c1=22 and c2='BB' where id=2;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from t1;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 11 | AA |
| 2 | 0 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)
这是由于实际被转换为类似下面的逻辑了:
(1)update t1 set c2=('BB' and c1= 22) where id=2;
(2)update t1 set c1=(22 and c2='BB') where id=2;
由于第一个语句中'BB'不能转换为逻辑上的true/false,因此报错了
第二个语句中22为true,c2='BB'为false,因此整个逻辑表达式的结果为false,即0,因此最终结果是id=2的数据c1字段被更新为0。
实测发现该问题在5.7、8.0、MGR环境中都存在,我们自己的脚本审核平台也有此问题,需要特别关注!!!
附:
mysql的update语法:

oracle的update语句:

SQL> update t1 set c1=22 and c2='BB' where id=2;
update t1 set c1=22 and c2='BB' where id=2
*
ERROR at line 1:
ORA-00933: SQL command not properly ended
参考文档:
https://blog.csdn.net/weixin_31208627/article/details/113455985
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26451536/viewspace-2846420/ ,如需转载,请注明出处,否则将追究法律责任。