兩個看似奇怪的MySQL語句問題

jeanron100發表於2018-03-28

兩個看似奇怪的MySQL語句問題

今天同事給了我一個檔案需要更新下CMDB的資料,提供的內容是excel的形式,因為條目比較多,我需要做一些轉換,批次修改成對應的SQL語句,因為只有我知道這個邏輯,所以這個轉換工作由我來做。

本來看起來很簡單的一個問題,結果因為不經意的操作出了兩個問題,會牽扯出來兩條有趣的SQL問題。

首先excel資料類似下面的形式:

TEST1 10.0.0.1 7382 TEST2 10.0.0.2 7388 TEST21 10.0.0.21 7389

所以我需要把內容做一個簡單的轉換,比如使用awk或者使用文字編輯器來做都可以。

我需要把資料轉換成SQL語句,類似下面的形式:

update cmdb_server set server_app_code = trim('TEST1      ') where server_ip_addr=trim('10.0.0.1 ') and server_db_port=7382; 

這樣就可以批次生成大量的update語句,更新即可。

我從開始就犯了一個低階錯誤。

我把語句給轉換成了這樣,很快就編輯好了,但是執行語句之後發現沒有生效,真是奇怪,自己抽出一條語句來單獨執行看看,發現結果竟然有這樣的提示,影響到的行數有500多行,這看起來就麻煩了。

update cmdb_server set server_app_code = trim('TEST1      ') and server_ip_addr=trim('10.0.0.1 ') and server_db_port=7382; Query OK, 0 rows affected (0.01 sec) Rows matched: 537 Changed: 0 Warnings: 0

原來,是update語句竟然where字句部分讓我寫成了and,這種語句竟然能夠成功執行,我想看看這類語句到底是個什麼邏輯。

建立一個表test,有3個欄位

mysql> create table test(col1 int,col2 varchar(30),col3 varchar(30)); Query OK, 0 rows affected (0.11 sec)

插入3條資料

mysql> mysql> insert into test values (1,'aa','aaa'); Query OK, 1 row affected (0.07 sec) mysql> insert into test values (2,'bb','aaab'); Query OK, 1 row affected (0.00 sec) mysql> insert into test values (3,'cc','aaac'); Query OK, 1 row affected (0.00 sec)

然後使用這種奇怪的update,看看執行的結果到底是什麼樣的。

mysql> update test set col1=4 and col2='cc' and col3='aaac'; Query OK, 3 rows affected (0.07 sec) Rows matched: 3 Changed: 3 Warnings: 0

檢視結果,發現會把原來的col1列給重新整理,標記為0和1,如果對映到了就是1,否則就是0,但是真正的資料沒有正常變更。

mysql> select *from test; +------+------+------+ | col1 | col2 | col3 | +------+------+------+ | 0 | aa | aaa | | 0 | bb | aaab | | 1 | cc | aaac | +------+------+------+ 3 rows in set (0.00 sec)

所以這個問題牽扯出來一個還蠻意思的問題。

修改語句之後,資料還是沒有變更過來,這個時候碰到了一個詭異的問題,

上面的update語句手工複製過來能夠正常執行,但是在文字里就不可以。反反覆覆試了多次,還可以復現,讓我都有些懷疑人品了。

情況大概是這樣,透過縮小範圍,能夠定位出來是在trim的部分。

手工執行,可以看到trim的部分是生效了。

mysql> select concat(rtrim('101022152a  '),'tttt'); +--------------------------------------+ | concat(rtrim('101022152a  '),'tttt') | +--------------------------------------+ | 101022152atttt | +--------------------------------------+ 1 row in set (0.00 sec)

而如果編輯這個檔案,執行的時候trim的部分卻沒有生效。

mysql> source a.sql +----------------------------------------------+ | concat(trim('10.10.22.152 '),'10.10.22.152') | +----------------------------------------------+ | 10.10.22.152 10.10.22.152 | +----------------------------------------------+ 1 row in set (0.00 sec)

檢視檔案的內容

mysql> system cat a.sql 
select concat(trim('10.10.22.152 '),'10.10.22.152');

而這個問題我猶豫了一會,突然想明白了,我換個思路來解答。

我把文字中的那段內容簡單修改了下,保持空格的部分不變,然後使用hex來解析。

mysql> system cat a.sql 
select hex(concat(trim('2 '),'1')); +-----------------------------+ | hex(concat(trim('2 '),'1')) | +-----------------------------+ | 320931 | +-----------------------------+ 1 row in set (0.00 sec)

這個時候就明白了,32是2的ascii碼值,同理,1對應的是31,而09對應的是製表符,也就是\t這樣的符號,是不可見的。

明白了原因,來回溯過程,會發現我使用文字編輯器的時候還是可能生成這個製表符的,不能直接把鍋扣給工具,還是自己觸發的,當然這個過程中因為字元不可見,所以也就沒有重視。

同事也給我提供了一個蠻有意思的類似問題,大家一睹為快,這類問題簡直會讓你懷疑人生。

兩個看似奇怪的MySQL語句問題

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2152374/,如需轉載,請註明出處,否則將追究法律責任。

相關文章