• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase
您的位置:首页 > 数据库 >Mysql > MySQL中隐式转换方法

MySQL中隐式转换方法

作者:匿名 字体:[增加 减小] 来源:互联网 时间:2018-12-05

匿名通过本文主要向大家介绍了MySQL,方法,隐式等相关知识,希望本文的分享对您有所帮助
隐式转化规则

官方文档中关于隐式转化的规则是如下描述的:

If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.

  • If both arguments in a comparison operation are strings, they are compared as strings.

  • If both arguments are integers, they are compared as integers.

  • Hexadecimal values are treated as binary strings if not compared to a number.

  • If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments to IN()! To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type.
    A single-row subquery from a table or tables is not considered a constant. For example, if a subquery returns an integer to be compared to a DATETIME value, the comparison is done as two integers. The integer is not converted to a temporal value. To compare the operands as DATETIME values, use CAST() to explicitly convert the subquery value to DATETIME.

  • If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.

  • In all other cases, the arguments are compared as floating-point (real) numbers.

翻译为中文就是:

    1. 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换

    2. 两个参数都是字符串,会按照字符串来比较,不做类型转换

    3. 两个参数都是整数,按照整数来比较,不做类型转换

    4. 十六进制的值和非数字做比较时,会被当做二进制串

    5. 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp

    6. 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较

    7. 所有其他情况下,两个参数都会被转换为浮点数再进行比较

问题描述

  • where 条件语句里,字段属性和赋给的条件,当数据类型不一样,这时候是没法直接比较的,需要进行一致转换

  • 默认转换规则是:

    • 不同类型全都转换为浮点型(下文都说成整型了,一个意思)

    • 如果字段是字符,条件是整型,那么会把表中字段全都转换为整型(也就是上面图中的问题,下面有详细解释)

转换总结

  1. 字符转整型

    • 字符开头的一律为0

    • 数字开头的,直接截取到第一个不是字符的位置

  2. 时间类型转换

    • 按照字符串进行截取

    • 23:12:13 -> 2023-12-13(这个后文有讨论)

    • 对于不符合的时间值,如10:12:32等,会变为 0000-00-00 或为 空

    • cast函数只能转datetime,不能转timestamp

    • 如果按照timestamp来理解,因为timestamp是有范围的('1970-01-01 00:00:01.000000' to'2038-01-19 03:14:07.999999'),所以只能是2023年,而不能是1923年

    • 直接截取time字段

    • 直接截取date字段

    • 无意义,直接为 00:00:00

    • 追加 00:00:00

    • date 转 datetime 或者 timestamp

    • date 转 time

    • datetime 或者 timestamp 转 date

    • datetime 或者 timestamp 转 time

    • time 转 datetime 或者 timestamp

    • time和datetime转换为数字时,会变为双精度,加上ms(版本不同不一样)

案例分析

  • 表结构,name字段有索引

-- 注意name字段是有索引的CREATE TABLE `t3` (  `id` int(11) NOT NULL,  `c1` int(11) NOT NULL,  `name` varchar(100) NOT NULL DEFAULT 'fajlfjalfka',  KEY `name` (`name`),  KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin11 row in set (0.00 sec)
-- 模拟线上一个隐式转换带来的全表扫面慢查询-- 发生隐式转换
xxxx.test> select * from t3 where name = 0;
+----+----+-------------+
| id | c1 | name        |
+----+----+-------------+
|  1 |  2 | fajlfjalfka |
|  2 |  0 | fajlfjalfka |
|  1 |  2 | fajlfjalfka |
|  2 |  0 | fajlfjalfka |
+----+----+-------------+
4 rows in set, 4 warnings (0.00 sec)-- 上述SQL执行计划是全表扫描,扫描后,字符转整型,都是0,匹配上了条件,全部返回
xxxx.test> desc select * from t3 where name = 0;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t3    | ALL  | name          | NULL | NULL    | NULL |    4 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)-- 加上单引号后,是走name索引的,非全表扫描
xxxx.test> desc select * from t3 where name = '0';
+----+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref   | rows | Extra                 |
+----+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | t3    | ref  | name          | name | 102     | const |    1 | Using index condition |
+----+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
1 row in set (0.00 sec)-- 走索引,没返回
xxxx.test>  select * from t3 where name = '1';
Empty set (0.00 sec)

解释

  • 如果条件写0或者1,会进行全表扫面,需要把所有的name字段由字符全都转换为整型,再和0或者1去比较。由于都是字母开头的字符,会全都转为为0,返回的结果就是所有行。

  • 那有人问了,为什么不把条件里的 0 自动改成 '0' ?见下文。

转换举例

-- 字符开头,直接是0
xxxx.test> select cast('a1' as unsigned int) as test ;
+------+
| test |
+------+
|    0 |
+------+
1 row in set, 1 warning (0.00 sec)

xxxx.test> show warnings;
+---------+------+-----------------------------------------+
| Level   | Code | Message                                 |
+---------+------+-----------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: 'a1' |
+---------+------+-----------------------------------------+
1 row in set (0.00 sec)-- 开头不是字符,一直截取到第一个不是字符的位置
xxxx.test> s
  


 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 分享下mysql各个主要版本之间的差异
  • MySQL essential版本和普通版本有什么区别?
  • redhat 5.4下安装MYSQL全过程
  • 如何用SQL命令查看Mysql数据库大小
  • 解析mysql中如何获得数据库的大小
  • 解析mysql修改为utf8后仍然有乱码的问题
  • 5个常用的MySQL数据库管理工具详细介绍
  • 解析在MySQL里创建外键时ERROR 1005的解决办法
  • 解析远程连接管理其他机器上的MYSQL数据库
  • mysql 精简过程(删除一些文件)

相关文章

  • 2017-05-11Mysql 建库建表技巧分享
  • 2018-12-05Mysql中文乱码问题完美解决方案
  • 2018-12-05sql图形化操作设置级联更新和删除
  • 2018-12-05mysql常用的语句_MySQL
  • 2018-12-05MySQL基本调度方法浅析
  • 2018-12-05监视SQLServer数据库镜像[图文]
  • 2018-12-05MySQL多表联合查询说明
  • 2018-12-05sqlserver 数据类型转换小实验
  • 2018-12-05mysql 复制记录实现代码
  • 2018-12-05MySQL之-linux下MYSQL定时备分代码示例

文章分类

  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase

最近更新的内容

    • 详解MySQL 4G内存服务器配置优化
    • 全面解析Windows下安装 mysql5.7的方法_MySQL
    • MYSQL数据库数据拆分之分库分表总结_MySQL
    • MySQL5创建存储过程的示例
    • 关于Oracle 11g服务器安装详细步骤图文详解教程
    • 在Oracle中利用SQL_TRACE跟踪SQL的执行
    • 模糊查询的通用存储过程
    • mysql 存储过程输入输出参数示例
    • MySQL笔记之函数查询的使用
    • MySQL存储毫秒数据的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有