当我们对不同类型的值进行比较的时候,为了使得这些数值「可比较」(也可以称为类型的兼容性),MySQL会做一些隐式转化(Implicit type conversion)。比如下面的例子:
mysql> SELECT 1+'1'; -> 2 mysql> SELECT CONCAT(2,' test'); -> '2 test'
很明显,上面的SQL语句的执行过程中就出现了隐式转化。并且从结果们可以判断出,第一条SQL中,将字符串的“1”转换为数字1,而在第二条的SQL中,将数字2转换为字符串“2”。
MySQL也提供了CAST()
函数。我们可以使用它明确的把数值转换为字符串。当使用CONCA()
函数的时候,也可能会出现隐式转化,因为它希望的参数为字符串形式,但是如果我们传递的不是字符串呢:
mysql> SELECT 38.8, CAST(38.8 AS CHAR); -> 38.8, '38.8' mysql> SELECT 38.8, CONCAT(38.8); -> 38.8, '38.8'
隐式转化规则
官方文档中关于隐式转化的规则是如下描述的:
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.
翻译为中文就是:
两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换 两个参数都是字符串,会按照字符串来比较,不做类型转换 两个参数都是整数,按照整数来比较,不做类型转换 十六进制的值和非数字做比较时,会被当做二进制串 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较 所有其他情况下,两个参数都会被转换为浮点数再进行比较
所以需要注意安全问题:
写SQL时一定要检查参数类型与数据库字段类型一致,(如果参数不一致,也要使用CAST函数显示转换成一致)否则造成隐式类型转换,不走索引,后果简直不堪设想,
cast函数的使用
cast(字段名, as 要转换的字段名), 其中类型可以为:
char(N) _ 字符串类型
DATA _ 日期类型
DATETIME 日期和时间型
DECIMAL float型
SIGNED int
TIME 时间型
【date】 — 2015-11-03 15:31:26 select cast(date as signed) as date from table1; 结果如下: date 20151103153126 select cast(date as char) as date from table1; 结果如下: date 2015-11-03 15:31:26 select cast(date as datetime) as date from table1; 结果如下: date 2015-11-03 15:31:26 select cast(date as date) as date from table1; 结果如下: date 2015-11-03 select cast(date as time) as date from table1; 结果如下: date 15:31:26 这里date对应日期,time对应时间