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'
相关文章
相关标签/搜索