也议MySQL中隐式转换

1. 环境说明

blog地址:http://blog.csdn.net/hw_libo/article/details/39252427

RHEL 6.4 x86_64 + MySQL 5.6.19

测试表:

MySQL [test]> show create table emp\G
*************************** 1. row ***************************
       Table: emp
Create Table: CREATE TABLE `emp` (
  `EMPNO` int(11) NOT NULL,
  `ENAME` varchar(15) NOT NULL,
  `JOB` varchar(15) NOT NULL,
  `MGR` int(11) DEFAULT '0',
  `HIREDATE` timestamp NULL DEFAULT NULL,
  `SAL` int(20) DEFAULT '0',
  `COMM` int(11) DEFAULT '0',
  `DEPTNO` int(11) NOT NULL,
  PRIMARY KEY (`EMPNO`),
  KEY `idx_deptno` (`DEPTNO`),
  KEY `idx_sal` (`SAL`),
  KEY `idx_comm` (`COMM`),
  KEY `idx_ename` (`ENAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
</pre><pre name="code" class="sql">MySQL [test]> select * from emp;
+-------+--------+-----------+------+---------------------+------+------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE            | SAL  | COMM | DEPTNO |
+-------+--------+-----------+------+---------------------+------+------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800 | NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600 |  300 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250 |  500 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975 |    0 |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250 | 1400 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850 |    0 |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450 |    0 |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000 | NULL |     20 |
|  7839 | KING   | PRESIDENT |    0 | 1981-11-17 00:00:00 | 5000 |    0 |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500 |    0 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100 |    0 |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950 |    0 |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000 |    0 |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300 |    0 |     10 |
|  7936 | 23456  | BOSCO-DBA | 7788 | 2014-09-13 16:13:56 | 2450 |  800 |     10 |
+-------+--------+-----------+------+---------------------+------+------+--------+
15 rows in set (0.00 sec)

2. 数值类型(int)

首先提个问题,如上测试表emp中empno是主键,类型为int,那么:

select * from emp where empno='7788';

会产生隐式转换吗?

下面实验证明:

MySQL [test]> select * from emp where empno=7788;
+-------+-------+---------+------+---------------------+------+------+--------+
| EMPNO | ENAME | JOB     | MGR  | HIREDATE            | SAL  | COMM | DEPTNO |
+-------+-------+---------+------+---------------------+------+------+--------+
|  7788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000 | NULL |     20 |
+-------+-------+---------+------+---------------------+------+------+--------+
1 row in set (0.00 sec)

MySQL [test]> explain select * from emp where empno=7788;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | emp   | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)

MySQL [test]> select * from emp where empno='7788';
+-------+-------+---------+------+---------------------+------+------+--------+
| EMPNO | ENAME | JOB     | MGR  | HIREDATE            | SAL  | COMM | DEPTNO |
+-------+-------+---------+------+---------------------+------+------+--------+
|  7788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000 | NULL |     20 |
+-------+-------+---------+------+---------------------+------+------+--------+
1 row in set (0.00 sec)

MySQL [test]> explain select * from emp where empno='7788';
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | emp   | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)

可见,针对数据类型字段,即使类型不一致,并不影响是否使用索引,执行计划是一样的,不会产生隐式转换。但仍然建议在生产库中尽量避免出现这样的SQL。

注意:

数值类型有一种隐式转换,如果以数字开关的,后面的字符将被截断,只取前面的数字值,如果不以数字开关的将被置为0。如下:

MySQL [test]> select * from emp where empno='7788ab12';   ## 这个就相当于empno=7788,后面的ab12将被截断,并且不影响索引的使用
+-------+-------+---------+------+---------------------+------+------+--------+
| EMPNO | ENAME | JOB     | MGR  | HIREDATE            | SAL  | COMM | DEPTNO |
+-------+-------+---------+------+---------------------+------+------+--------+
|  7788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000 | NULL |     20 |
+-------+-------+---------+------+---------------------+------+------+--------+
1 row in set, 1 warning (0.00 sec)

MySQL [test]> show warnings;
+---------+------+----------------------------------------------+
| Level   | Code | Message                                      |
+---------+------+----------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '7788ab12' |
+---------+------+----------------------------------------------+
1 row in set (0.00 sec)

MySQL [test]> select * from emp where empno='ab7788';   ## 这个就相当于empno=0
Empty set (0.01 sec)

3. 字符类型(varchar)

同样,针对测试表emp中的ename字段(varchar类型),上面有一辅助索引idx_ename,并且ename中有一个值是全数字的,若有这样的查询:

select * from emp where ename=23456;

上面的SQL会不会出现隐式转换呢?

下面实验证明:

MySQL [test]> select * from emp where ename='23456';
+-------+-------+-----------+------+---------------------+------+------+--------+
| EMPNO | ENAME | JOB       | MGR  | HIREDATE            | SAL  | COMM | DEPTNO |
+-------+-------+-----------+------+---------------------+------+------+--------+
|  7936 | 23456 | BOSCO-DBA | 7788 | 2014-09-13 16:13:56 | 2450 |  800 |     10 |
+-------+-------+-----------+------+---------------------+------+------+--------+
1 row in set (0.00 sec)

MySQL [test]> explain select * from emp where ename='23456';   ## 正常来说,可以使用到索引idx_ename
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key       | key_len | ref   | rows | Extra                 |
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | emp   | ref  | idx_ename     | idx_ename | 47      | const |    1 | Using index condition |
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----------------------+
1 row in set (0.00 sec)
MySQL [test]> select * from emp where ename=23456;   ## 当varchar类型不对时,仍然是可以查出结果
+-------+-------+-----------+------+---------------------+------+------+--------+
| EMPNO | ENAME | JOB       | MGR  | HIREDATE            | SAL  | COMM | DEPTNO |
+-------+-------+-----------+------+---------------------+------+------+--------+
|  7936 | 23456 | BOSCO-DBA | 7788 | 2014-09-13 16:13:56 | 2450 |  800 |     10 |
+-------+-------+-----------+------+---------------------+------+------+--------+
1 row in set, 14 warnings (0.00 sec)

MySQL [test]> explain select * from emp where ename=23456;   ## 当varchar类型不匹配时,索引无效了,选择了全表扫描
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | emp   | ALL  | idx_ename     | NULL | NULL    | NULL |   15 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

可见,如果是字符类型,当出现类型不一致时,是会影响索引的使用的,会产生隐式转换的。

blog地址:http://blog.csdn.net/hw_libo/article/details/39252427

-- Bosco  QQ:375612082

---- END ----

-------------------------------------------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

时间: 2024-09-29 10:07:39

也议MySQL中隐式转换的相关文章

Scala中隐式转换内幕操作规则揭秘

Scala中隐式转换内幕操作规则揭秘.最佳实践及其在Spark中的应用,具体来说就是通过类的伴生对象实现隐式转换,而不用 Import操作,在spark的RDD对象中用得很多 例子:在spark中,RDD就是通过RDD类的伴生对象实现隐式转换 object RDD { implicit def rddToPairRDDFunctions[K, V](rdd: RDD[(K, V)]) (implicit kt: ClassTag[K], vt: ClassTag[V], ord: Orderin

Scala 深入浅出实战经典 第65讲:Scala中隐式转换内幕揭秘、最佳实践及其在Spark中的应用源码解析

王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 腾讯微云:http://url.cn/TnGbdC 360云盘:http://yunpan.cn/cQ4c2UALDjSKy 访问密码 45e2土豆:http://www.tudou.com/programs/view/NGgUD5FBQaA/优酷:http://v.youku.com/v_show/id_

第59讲:Scala中隐式转换初体验

今天学习了下隐式转换的内容.所谓隐式转换,就是说,一个实例拥用1 2 3方法,但是当它需要4方法的时候,它没有,但是却可以通过转换成另一种类型来调用4方法,而且这种转换是自动转换不需要人为干预的,这种形为就叫做隐式转换.让我们通过实例来分析一下: import java.io.Fileimport scala.io.Source class RichFile(val file:File){  def read = Source.fromFile(file.getPath).mkString} o

关于MySQL隐式转换

一.如果表定义的是varchar字段,传入的是数字,则会发生隐式转换. 1.表DDL 2.传int的sql 3.传字符串的sql 仔细看下表结构,rid的字段类型: 而用户传入的是int,这里会有一个隐式转换的问题,隐式转换会导致全表扫描. 把输入改成字符串类型,执行计划如下,这样就会很快了. 此外,还需要注意的是: 数字类型的0001等价于1 字符串的0001和1不等价 二.如果表定义的是int字段,传入的是字符串,在不超过int范围内,不会发生隐式转换,如果超出范围并且比较大小(以字符串类型

Scala中隐式转换内幕操作规则揭秘、最佳实践及其在Spark中的应用源码解析之Scala学习笔记-55

package com.leegh.implicits import scala.io.Sourceimport java.io.File /** * @author Guohui Li */class RicherFile(val file: File) { def read = Source.fromFile(file.getPath).mkString} class File_Implicits(path: String) extends File(path)//伴生对象object Fi

SQL SERVER中隐式转换的一些细节浅析

其实这是一篇没有技术含量的文章,精通SQL优化的请绕道.这个缘起于在优化一个SQL过程中,同事问了我一个问题,为什么SQL中存在隐式转换,但是执行计划没有变? 我思索了一下,觉得这个问题也有点意思,说不定有些对隐式转换了解得不深入的同学都有此疑问,那么下面结合上下文场景做一个细节方面的解答. 我们一个系统中使用了ORMLite框架,粗心的开发人员弄出了不少下面这样的SQL语句,都存在隐式转换问题,如下所示,表machine_stop_alarm_msg 的结构如下,字段machine_no.st

scala中隐式转换之隐式转换调用类中本不存在的方法

/** * Created by root * Description : 隐式转换调用类中本不存在的方法 */ class Person(name : String){ def getPersonName = println("name = " + name) } object Type2Type{ implicit def type2(a : ImplicitTest2) = new Person("xiaoming") } class ImplicitTest

scala中隐式转换之隐式类

/** * Created by root * Description :隐式类: * 1.其所带的构造参数有且只能有一个:并且构造器的参数是转换之前的对象 * 2.隐式类必须被定义在类,伴生对象和包对象里 * 3.隐式类不能是case class(case class在定义会自动生成伴生对象与2矛盾) * 4.作用域内不能有与之相同名称的标示符 */ class ImplicitTest3 { def getName = "ImplicitTest3" } object Implic

scala中隐式转换之隐式值和隐式视图

/** * Created by root * Description : 隐式值和隐式视图 */ object ImplicitTest { def main(args: Array[String]): Unit = { // 隐式值 implicit val str = "hello" def fun(implicit s: String) = println(s) fun // 调用fun函数,编译器发现参数缺省,直接去作用域内查找隐式值,保证隐式值只有一个 // 隐式视图:隐式