評“MySQL 隱式轉換引起的執行結果錯誤”

cow977發表於2019-07-02

今天看到一篇關於MySQL隱式轉換引發執行結果錯誤的文章:

===========================================================================

今天給大家,帶來的例子是 MySQL Join過程中發生隱式轉換導致結果跟預期的不一樣的問題。

下面是 即將使用的表和插入資料的 指令碼

create table a (nntx_no int ) ;
create table b (nntx_no varchar(20) ) ;
root@mysql3306.sock>[test]>insert into a values (1772 ) ;
Query OK, 1 row affected (0.00 sec)
root@mysql3306.sock>[test]>insert into a values (1773 ) ;
Query OK, 1 row affected (0.00 sec)
root@mysql3306.sock>[test]>insert into b values ('1772' ) ;
Query OK, 1 row affected (0.00 sec)
root@mysql3306.sock>[test]>insert into b values ('1772.0 ~ 34' ) ;
Query OK, 1 row affected (0.01 sec)

下面是表資料

root@mysql3306.sock>[test]>select * from a ;
+---------+
| nntx_no |
+---------+
| 1772 |
| 1773 |
+---------+
2 rows in set (0.00 sec)
root@mysql3306.sock>[test]>select * from b ;
+-------------+
| nntx_no |
+-------------+
| 1772 |
| 1772.0 ~ 34 |
+-------------+
2 rows in set (0.00 sec)

執行如下SQL

select a.nntx_no, b.nntx_no
 -> from a
 -> left join b on a.nntx_no = b.nntx_no
 -> where 1=1
 -> and a.nntx_no = 1772;
+---------+-------------+
| nntx_no | nntx_no |
+---------+-------------+
| 1772 | 1772 |
| 1772 | 1772.0 ~ 34 |
+---------+-------------+

可以看到出了 兩行資料,但是其中第二行資料 顯然不符合我們的預期

但MySQL卻給我們了一個看似錯誤的結果!!!

現在我們來分析,這個結果的原因

root@mysql3306.sock>[test]>select a.nntx_no, b.nntx_no
 -> from a
 -> left join b on a.nntx_no = b.nntx_no
 -> where 1=1
 -> and a.nntx_no = 1772;
+---------+-------------+
| nntx_no | nntx_no |
+---------+-------------+
| 1772 | 1772 |
| 1772 | 1772.0 ~ 34 |
+---------+-------------+
2 rows in set, 2 warnings (0.00 sec)
root@mysql3306.sock>[test]>show warningsG
*************************** 1. row ***************************
 Level: Warning
 Code: 1292
Message: Truncated incorrect DOUBLE value: '1772.0 ~ 34'
*************************** 2. row ***************************
 Level: Warning
 Code: 1292
Message: Truncated incorrect DOUBLE value: '1772.0 ~ 34'
2 rows in set (0.00 sec)

從show warnings 中 可以看出一些端倪 有兩個warning

顯示 Truncated incorrect DOUBLE value: '1772.0 ~ 34'

說明 '1772.0 ~ 34' 轉換過程中,被截斷了

我們坐下如下實驗

root@mysql3306.sock>[test]>select '1772.0 ~ 34' + 0 ;
+-------------------+
| '1772.0 ~ 34' + 0 |
+-------------------+
| 1772 |
+-------------------+

說明 '1772.0 ~ 34' 字串轉換成數字的過程中 被轉換成1772 所以MySQL 給我們

得出了上面的結果!

那原因,已經知道了 剩下的就是怎樣處理了!

我們從上面的結果中已經知道,原因是字串變成數字的過程中被擷取導致的,

那解決方案就是,不進行數字型別轉換就可以了。

如下所示,用了 concat(a.nntx_no,'') 使數字型別變成字串型別,從而字串=字串

這樣就可以了 !!!

root@mysql3306.sock>[test]>select a.nntx_no, b.nntx_no
 -> from a
 -> left join b on concat(a.nntx_no,'') = b.nntx_no
 -> where 1=1
 -> and a.nntx_no = 1772;
+---------+---------+
| nntx_no | nntx_no |
+---------+---------+
| 1772 | 1772 |
+---------+---------+
1 row in set (0.00 sec)

以上就是,今天的內容

===========================================================================

這應該算了MySQL的一個Bug吧。
1、從CHAR到INT的轉換,不成功應該要報錯;
2、隱式轉換,應該要保持資料不丟失,即從INT到CHAR的轉換;


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

相關文章