~
考试月过去了,现在正在支教~全力补上
~
3.5.2类型转换
只要某个值的类型与上下文所要求得类型不相符,MySQL会根据操作符的类型自动进行类型转化。发生类型性转换的场合有以下几种
1、把操作符数转换为适合运算符计算的相应类型。
2、把函数参数转换成函数所期望的类型
3、把某个值转换为适合于存储在列里的另一种类型。
另外,还可以使用类型转换运算符或函数来完成显式类型转换。
可以根据系统变量character_set_connection 和collation_connection所指定的字符集和排序规则,将数字转换成字符串或时态值。只有character_set_connection位binary时,转换结果才会是一个二进制串,否则,结果为非二进制串。
1+ '2' ->3
+是一个 数字运算符,所以MySQL会要求两个操作数都是数字类型,因此会把字符串‘2’转换为数字2
repeat('x',concat(1,2,3)/10) ->'xxxxxxxxxxxx'
首先concat(1,2,3)会返回字符串‘123’。接着‘123’/10会转换为123/10,因为相除是一个算术运算符。此表达式的结果为12.3。由于repeat()函数需要的重复次数是一个整数,所以这个结果四舍五入为12。最后会重复‘x’12遍。
如果concat()的所有参数都是非二进制串,那么其结果也将是一个非二进制串。如果有参数为二进制串,那么其结果将是一个二进制串。其中,数字参数会转换为字符串,然后应用之前的规则。
默认情况下,MySQL会尽量把值转换为表达式所需要的类型,而不是产生错误。根据具体上下文的不同,MySQL会让值在三种通用类别(数字,字符串,日期/时间)进行转换。不过,值并不是总能从一种类型转换为另一种类型。如果某个值 在类型转换后,看起来并不像目标类型的合法值,那么这个转换就是失败的。最终得到的结果将为该类型的零值。
在数据输入期间,为防止把非法值转换成最近的合法值,可以启用严格模式,以便把此类问题当做错误报告出来。
MySQL还会执行某些微小的类型转换。如果在整数上下文中使用浮点数值,那么浮点数值会被转换。整数可以毫无问题的当做浮点数来使用。
除非上下文明确地表明需要一个数字,否则十六进制数常量会被当作二进制串来对待。在字符串上下文中,每两个十六进制数字会被转换为一个字符,最终结果为一个字符串
0x61 ->'a'
0x61 + 0 ->97
X'61' ->'a'
X'61'+0 ->97
concat(0x61) ->'a'
concat(0x61 + 0) ->'97'
concat(X'61') ->'a'
concat(X'61') ->'97'
对于比较操作中的十六进制常量,上下文会根据具体情况来确定是把它当成二进制串还是数字。
1.下面的表达式会把操作数当成二进制串,并按字节进行比较
0x0d0a = '\r\n' ->1
2.下面的表达式比较的是一个十六进制常量和一个数字,因此为了进行比较,该常量会先转换成数字
0x0a = 10 ->1
3.下面的表达式执行的是二进制串的比较。左操作数的第一个字节值比右操作数小,因此结果为假
0xee00 > 0xff ->0
4.在下面的表达式里,右操作数中的十六进制常量会被转化为一个数字,因为那是个算术运算。接着,为完成比较,左操作数也会转化为一个数字。最后,由于0xee00(60928)在数字上大于0xff(255),所以最终结果为真。
0xee00 > 0xff+0 ->1
使用字符集引导符或convert(),可以把十六进制常量强制转化成一个非二进制串
0x61 ->'a' ->'a'
0x61 ->'A' ->0
_latin1 0x61 = 'A' ->1
convert (0x61 using latin1) ='A' ->1
有些运算符会把操作数强制转化为它所期望的类型,而不管这些操作数原来是什么类型。
3+4 ->7
'3' + 4 ->7
'3' +'4' ->7
对于"字符串到数字"的转换,只是字符串里的某个地方包含一个数字还远远不够。MySQL并不会检查整个字符串,以期望找到某个数字;它只会检查字符串的开头部分是不是数字。如果不是,转换的结果即为0。
'1973-2-4' +0 ->1973
'12:14:01' +0 ->12
'23-skidoo' +0 ->23
'-23-skidoo'+0 ->-23
'carbon-14' +0 ->0
MySQL的"字符串到数字"的转换规则,适用于把看起来像数字的字符串转换为数字值:
'-428.9'+0 ->428.9
'3E-4' +0 ->0.0003
不过,这种转换对于看起来像十六进制敞亮的字符串不起作用,只有使用前导"0"的才可以转换
'0xff' +0 ->0
位运算符甚至比算术运算符还严格。它们不仅要求操作数时数字,而且还要求它们是整数(根据情况进行相应的类型转换)这意味着,对于像0.3这样的小数,即使它为非零值,也不会被当成逻辑真值。因为当它转换成整数时,所得结果为零。在下面几个表达式里,只有那些值大于1的操作数才会被认为是逻辑真值:
0.3|.04 ->0
1.3|.04 ->1
0.3&.04 ->0
1.3&.04 ->0
1.3&1.04 ->1
模式匹配运算符希望操作的是字符串。这意味着,可以把MySQL的模式匹配运算符用于数字,因为在查找匹配的过程中,它会把这些数字转换成字符串
12345 like '1%' ->1
12345 regexp '1.*5' ->1
大小比较运算符(<、<=、=等)跟上下文密切相关,也就是说,他们会根据操作数的类型来进行计算。下列表达式会比较两个操作数的数字大小,因为他们都是数字:
2<11 ->1
下列表达式涉及的操作符都是字符串,因为它们会按词法进行比较:
'2'<'11' ->1
在下列表达式里,两个操作数的类型各不相同,因此MySQL会按数字方式对他们进行比较。于是,这两个表达式的结果都为真:
'2'<11 ->1
2<'11' ->1
在进行比较运算时,MySQL会根据需要按以下规则对操作数进行类型转换。
1.除<=>运算符以外,所有涉及NULL值得比较结果都为NULL。(另外,<=>与=很像,只是NULL<=>NULL的结果为真,而NULL=NULL的结果为NULL)
2.如果两个操作数都是字符串,那么她们将按字符串进行词法比较。对于二进制串,会按字节逐个比较各个对应字节的数值。对于非二进制串,会使用表示字符串的字符集的排序序列,逐个字符的进行比较。如果字符串使用了不同的字符集,那么这个比较可能导致错误或者产生毫无意义的结果。对于非二进制串和二进制串之间的比较,按二进制串方式进行。
3.如果两个操作数都是整数,那么她们将按整数方式进行数字比较。
4.与数字进行比较的十六进制常量,会按二进制串进行比较。
5.除in()以外,如果有一个操作数为timestamp或datetime,而另一个操作数为常量,那么两个操作数会按timestamp值进行比较。这种做法很适合于各种ODBC应用程序的比较操作。
6.如果有一个操作数为小数,而另一个操作数为小数或整数,那么两个操作数会按小数进行比较;否则,按啥UN高精度浮点值进行比较。
7.除上述情况以外,比较操作中的操作数都将按照双精度浮点值进行数字比较。请注意,字符串与数字之间的比较也属于这种情况。字符串将被转换为一个双精度数,如果字符串看起来不像数字,那么转换结果将为0。例如,'14.3'将被黄钻华为14。3但'L4.3'会被转化为0。