dml中的and使用误区

xiaoxiao2021-02-27  142

下午刚刚在一个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。切记。

转载请注明原文地址: https://www.6miu.com/read-15229.html

最新回复(0)