dml中的and使用误区

下午刚刚在一个jira变更中的遇到问题,非常容易产生误使用,产生比较大的危害。大家看下。非常简单的一条SQL:

mysql> update order_original set audit_status=3 and is_queue=1 where id=16682331;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0


很快就执行完了。但是,大家留意到没? Changed: 0 ,即虽然Rows matched: 1,确实有 id=16682331这一行,但是没有更新成功。这时,很多人肯定想到,这里肯定就是已经被更新过了啊。我们来看下:

mysql> select audit_status,is_queue from order_original where id=16682331;
+--------------+----------+
| audit_status | is_queue |
+--------------+----------+
| 1 | 1 |
+--------------+----------+
1 row in set (0.00 sec)


是不是很奇怪,并不是我们想要的结果。OK,我们把SQL改变一下写法:

mysql> update order_original set audit_status=3, is_queue=1 where id=16682331;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0


注意,是不是已经是Changed: 1 ?我们实例再查一下:

mysql> select audit_status,is_queue from order_original where id=16682331;
+--------------+----------+
| audit_status | is_queue |
+--------------+----------+
| 3 | 1 |
+--------------+----------+
1 row in set (0.00 sec)


确实数据update成功了。到这里大家应该明白了吧。如果还不明白,我们再做一个更明显的实验,帮忙看清本质的原因:

mysql> create table test(a int,b int,c int);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into test values(1,2,3);
Query OK, 1 row affected (0.00 sec)

mysql> update test set b=99 and c=3 where a=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from test;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | 1 | 3 |
+------+------+------+
1 row in set (0.00 sec)

mysql> update test set b=99 and c=5 where a=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from test;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | 0 | 3 |
+------+------+------+
1 row in set (0.01 sec)


即在update中,set 列=值,这个等号后面把and看成一个位运算,当后面的结果存在或正确时(set b=99 and c=3),那就是set 列=1,错误或不存在时(set b=99 and c=5)就是0。

因此,这个SQL的写法的危害是极大的,如果一个SQL执行报错,那APP报错,我们会去查找它的原因。

但如果它是一个错误的SQL,却被执行成功了,返回APP执行成功,那我们就感知不到它。而它一定会导致更新成一个完全错误的值,使我们的数据产生极大的破坏。

幸好这次只是在jira只执行了一次,但如果这样的SQL上线后被APP反复执行,将会给我们的线上数据产生不可估量的破坏。


因此必须避免在update的列更新中使用and。切记。

猜你喜欢

转载自blog.csdn.net/russ44/article/details/72884930