MySQL 字符串類型用數字能夠查出來 MySQL字符串類型會轉換成數字 MySQL隱式類型轉換

1、發現問題sql

一、在一次MySQL查詢中,某字段爲 varchar 字符串類型,傳入參數值爲 int 數字類型,發現查詢的結果和預期的不一致。 如: 某兩列 name='11' , name = '11aa' 。 where name = 11 , 能夠查到 '11' 和 '11aa' 兩個結果,這裏是錯誤的;而 where name ='11' ,能獲得預期結果。安全

 

二、反之,字段爲 int 數字類型,傳入參數值爲 varchar 字符串類型,也能查到數據,一樣查詢的結果和預期的不一致。如:age=2的數據有2條。where age = 2 , 能夠正常查到數據 ; 而 where age = '2aabbcc',查到的數據結果和 where age = 2 是同樣的,這裏是錯誤的,應該查不到數據。測試

 

2、代碼理解spa

一、針對【一】中的問題,描述的很差理解,晦澀難懂,下面用代碼加以理解,推進理解問題!3d

二、在MySQL數據中,建立一個 implicit 表 , 以下: (MySQL version 5.7+)code

SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for implicit
-- ----------------------------
DROP TABLE IF EXISTS `implicit`;
CREATE TABLE `implicit` (
  `id` varchar(255) NOT NULL COMMENT '編號',
  `name` varchar(255) DEFAULT NULL COMMENT '名稱',
  `age` int(11) DEFAULT NULL COMMENT '年齡',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='MySQL Implicit conversion (MySQL 隱式類型轉換)';
 
-- ----------------------------
-- Records of implicit
-- ----------------------------
INSERT INTO `implicit` VALUES ('11', '小明', '2');
INSERT INTO `implicit` VALUES ('11qq', '小紅', '2');
INSERT INTO `implicit` VALUES ('12', '小新', '54');
INSERT INTO `implicit` VALUES ('tt11', '小剛', '92');

三、implicit 表數據以下:blog

 image

 

3、針對問題進行測試ci

一、字段類型是 varchar 字符串,傳入參數爲 int 數字類型 。rem

1.一、-- 字段類型是 varchar ,傳入參數是 varchar 【預期正確結果】字符串

SELECT * FROM implicit a WHERE a.id = '11' ;

image

1.二、-- 字段類型是 varchar , 傳入參數是 int 【錯誤結果】

SELECT * FROM implicit a WHERE a.id = 11 ;

image

二、字段類型是 int 數字類型,傳入參數爲 varchar 字符串類型。

2.一、-- 字段類型是 int類型,傳入參數是 int類型 【預期正確結果】

SELECT * FROM implicit a WHERE a.age = 2 ;

image

2.二、-- 字段類型是 int類型,傳入參數是varchar類型 【錯誤結果】

SELECT * FROM implicit a WHERE a.age = '2aa' ;

image

4、問題緣由及避免

一、緣由: 當MySQL字段類型和傳入條件數據類型不一致時,會進行隱形的數據類型轉換(MySQL Implicit conversion)

二、若字符串是以數字開頭,且所有都是數字,則轉換爲數字結果是整個字符串;部分是數字,則轉換爲數字結果是截止到第一個不是數字的字符爲止。 理解: varchar str = "123dafa",轉換爲數字是123 。 SELECT '123dafa'+1 ; --- 124 。

三、若字符串不是以數字開頭,則轉換爲數字結果是 0 。 varchar str = "aabb33" ; 轉換爲數字是 0 。 SELECT 'aabb33'+100 ; --- 100 。

四、更多隱式轉換規則摘錄:

兩個參數至少有一個是 NULL 時,比較的結果也是 NULL,例外是使用 <=> 對兩個 NULL 作比較時會返回 1,這兩種狀況都不須要作類型轉換
兩個參數都是字符串,會按照字符串來比較,不作類型轉換
兩個參數都是整數,按照整數來比較,不作類型轉換
十六進制的值和非數字作比較時,會被當作二進制串
有一個參數是 TIMESTAMP 或 DATETIME,而且另一個參數是常量,常量會被轉換爲 timestamp
有一個參數是 decimal 類型,若是另一個參數是 decimal 或者整數,會將整數轉換爲 decimal 後進行比較,若是另一個參數是浮點數,則會把 decimal 轉換爲浮點數進行比較
全部其餘狀況下,兩個參數都會被轉換爲浮點數再進行比較。
 
5、問題總結

一、MySQL 隱式轉換問題,隱藏的深,不容易被發現,在進行 delete , update 等操做時,一不當心很容易大問題,從而形成事故。

二、對於 delete , update 等操做時,建議先使用 select 語句,看看獲取的結果和預期的是否一致,再進行操做,相對會更安全一些。

三、爲了便於更好理解,MySQL 隱式轉換規則,增長下面sql測試理解。

3.一、SELECT 'a10'+10 ; -- 10
SHOW WARNINGS ; -- WARNINGS: Truncated incorrect DOUBLE value: 'a10'
查看warnings能夠看到隱式轉化把字符串轉爲了double類型。可是由於字符串是非數字型的,因此就會被轉換爲0,所以最終計算的是0+10=10 .
 
3.二、SELECT '10a'+10 ; -- 20 
SHOW WARNINGS ; -- WARNINGS: Truncated incorrect DOUBLE value: '10a'
 
3.三、SELECT 'a'=0 ; -- 1 , 至關於 true 
SHOW WARNINGS ; -- WARNINGS: Truncated incorrect DOUBLE value: 'a'
 
3.四、SELECT 'a23423' = 0 ; -- 1 , 至關於 true 
SHOW WARNINGS ; -- WARNINGS:Truncated incorrect DOUBLE value: 'a23423'
 
3.五、SELECT '11dafdfwwe'=11; -- 1, 至關於 true 
SHOW WARNINGS ; -- WARNINGS:Truncated incorrect DOUBLE value: '11dafdfwwe'
 
3.六、SELECT 11= 11 ; -- 1, 至關於 true 
SHOW WARNINGS ; -- 無 
 
3.七、SELECT 'abc'='abc' ; -- 1, 至關於 true 
SHOW WARNINGS ; -- 無 
 
3.八、SELECT 'abc'='abc232322' ; -- 0 , 數據類型同樣,不會進行轉換 
SHOW WARNINGS ; -- 無 
 
3.九、SELECT 'a'+'b'; -- 0 , 都轉換爲0了, 0+0=0 。
SHOW WARNINGS ; -- WARNINGS: Truncated incorrect DOUBLE value: 'a' , Truncated incorrect DOUBLE value: 'b'
 
3.十、SELECT 'a'+'b'='c' ; -- 1 ,等價於 0+0=0 --> 0=0=1。
   SHOW WARNINGS ; -- WARNINGS: Truncated incorrect DOUBLE value: 'a' , Truncated incorrect DOUBLE value: 'b' , Truncated incorrect DOUBLE value: 'c'
相關文章
相關標籤/搜索