mysql資料庫UPDATE語句一個bug分析

來源:互聯網
上載者:User


這個我認為的bug,反饋給MySQL官方,但是MySQL官方認為這並不是一個bug,並給出瞭解釋,我認為這個解釋是合理的,但是不可避免的是這條語句實在太危險了。

問題描述

樣本表結構與表資料:

# 表結構
mysql> show create table t;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------+
| t | CREATE TABLE `t` (
 `id` int(11) DEFAULT NULL,
 `c1` int(11) DEFAULT NULL,
 `c2` varchar(16) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

# 表資料
mysql> select * from t;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 1 | A |
| 2 | 2 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)
正常的UPDATE語句應該長這樣子的,SET後接的並欄欄位分隔字元為”逗號(,)”:

mysql> select * from t;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 1 | A |
| 2 | 2 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)

mysql> update t 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 t;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 11 | AA |
| 2 | 2 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)
不合理的UPDATE應該是什麼樣子的呢,是將SET後接的並欄欄位分隔字元改為”AND”, 注意這樣寫的話,MySQL並不會報錯,還會執行成功,但是語義完全和”逗號”作為分隔字元是兩碼事 :

# 先來個實驗
mysql> select * from t;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 1 | A |
| 2 | 2 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)

mysql> update t set c1=11 and c2='AA' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from t;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 0 | A |
| 2 | 2 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)
# 實驗走到這裡,覺得這個update不是我想要的,但是這個c1咋變為0了呢,c2咋沒變呢?


# 再來個實驗
mysql> select * from t;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 1 | A |
| 2 | 2 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)

mysql> update t set c2='AA' and c1= 11 where id=1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 1

mysql> select * from t;
+------+------+------+
| id | c1 | c2 |
+------+------+------+
| 1 | 1 | 0 |
| 2 | 2 | B |
| 3 | 3 | C |
+------+------+------+
3 rows in set (0.00 sec)
# 咦?這裡c2變了,咋變為了0呢?我明明是個字母啊,再怎麼改也不能改成一個字串型數字啊?c2咋依舊沒變呢?
問題原因

原來在UPDATE … SET後接分隔字元為”AND”的語句,會處理成邏輯運算true(1) / false(0),直接上實驗好了==

# 第一個實驗解析
update t set c1=11 and c2='AA' where id=1;
# 在這條語句中MySQL將c1=11 and c2='AA'解析成了c1=(11 and c2='AA'),而在這張表中(11 and c2='AA')是一個假語句(false),所以MySQL將c1值解析為c1=0
mysql> select 11 and c2='AA' from t where id=1;
+----------------+
| 11 and c2='AA' |
+----------------+
| 0 |
+----------------+
1 row in set (0.00 sec)
# 所以最終出現了c1變為0,c2沒有任何改變的現象


# 第二個實驗解析
update t set c2='AA' and c1= 11 where id=1;
# 在這條語句中MySQL將c2='AA' and c1= 11解析成了c2=('AA' and c1= 11),而在這張表中('AA' and c1= 11)是一個假語句(false),所以MySQL將c2值解析為c2=0,然後隱式轉換,將'0'儲存到c2列
mysql> select 'AA' and c1= 11 from t where id=1;
+-----------------+
| 'AA' and c1= 11 |
+-----------------+
| 0 |
+-----------------+
1 row in set, 1 warning (0.01 sec)
# 所以最終出現了c2變為'0',c1依舊沒變

問題總結

這個問題告訴我們,SQL語句一定要寫規範了,執行SQL語句前一定要清楚這條SQL的運行邏輯,對於UPDATE/DELETE手動執行之前,一定要按照如下順序來==

begin;
update / delete ...;
select 校正資料;
commit; --資料校正成功
rollback; --資料校正失敗

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.