您的位置:首页 > 数据库 > MySQL

跟我一起学习MySQL技术内幕(第五版):(第三章学习日记15)

2016-06-11 23:43 441 查看
3.5表达式计算和类型转换

3.5.1编写表达式

3.5.1.1运算符类型

3.5.1.2运算符优先级

3.5.1.3表达式里的null值

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

3.5表达式计算和类型转换

表达式里包含子项和运算符,并且经过计算可以产生具体值.子项可以包含值,如常数,函数调用,表列引用,以及标量子查询.这些值可以用不同种类的运算符组合在一起,表达式的子项可以用括号进行分组.绝大部分情况下,表达式都是出现在输出列的列表里,以及select语句的where子句里.

select
concat (last_name,',',first_name),
timestampdiff(year,birth,death)
from president
where
birth >'1990-1-1' and death is not null;


每一个选择值代表一个表达式,与where自居的内容一样.表达式也可以出现在delete 和update 语句的where子句里,insert语句的values()子句里等.

当MySQL遇到表达式时,他会计算这个表达式,并产生一个结果.计算过程可能还会涉及到类型转换

3.5.1编写表达式

表达式可以很简单,甚至允许只为一个常量.

表达式可以使用函数调用.有些函数带有实参,有些则没有.函数的多个实参之间应该用逗号隔开.在调用内建函数时,它的参数之间允许出现空格.但在函数名和紧随其后的左括号之间,不允许出现空格.因为MySQL的解析器可能会错误的解释函数名.常见的是报语句出错.不过,通用的SQL的ignore_space模式,可以让MySQL允许内建函数名的后面出现空格,但这又会造成把函数名视为保留字的问题.

表达式里可以包含对表列的引用.对于最简单的情形,当可以根据上下文清楚地知道列所属的那个表时,只需给出该列的名字即可.在下面的两条select语句里,由于它们都只用到了一个表,所以尽管这两条语句里的列名完全一样,但这些列引用不会产生歧义;

select last_name, first_name from president;
select last_name, first_name from member;


如果还不清楚使用哪个表,则需要在列名的前面加上正确的表名进行限定.如果无法知道应该使用哪一个数据库,则需要在表名前面假声数据库名来进行限定.即使在不会产生歧义的上下文里,也可以使用这种更为具体的限定形式,以便看起来更加明确:

select
president.last_name,president.first_name,
member.last_name,member.first_name
from president inner join member
where president.last_name = member.last_name;

select sampdb.student.name from sampdb.student;


在表达式里,标量子查询可以用于提供单个值.这种子查询必须用括号括起来:

select * from president where birth = (select max(birth) from president);


最后,可以根据所有这些类型的值组成各种更加复杂的表达式.

3.5.1.1运算符类型

可以使用各种运算符把表达式里的各个子项组合在一起.这一节将描述这些运算符的功能j

算术运算符包括常见的加法减法乘法除法和取模. 当两个操作数都是整数时 对于运算符整个运算过程使用的都是bigint整数值 .如果两个操作数都是整数,且其中有一个是无符号数,那么结果也将是无符号数.对于除div以外的所有运算符,如果某个操作数是近似值,那么整个计算过程会遵循双精度浮点运算规则.对于字符串转换为数字的情形也是如此.因为字符串总是会被转换为双精度数.需要注意的是,如果某个整数运算涉及了很大的值,那么得到的结果是不可预测的.

运算符                  语法                    含义
'+'                     a+b                    两个操作数之和
'-'                     a-b                    两个操作数之差
'-'                     -a                     取反
'*'                     a*b                    两个操作数之积
'\'                     a\b                    两个操作数之商
div                     a div b                整除,两个操作数之商的整数部分
%                       a%b                    取模,即相除后的余数


逻辑运算符用于确定逻辑表达式的结果为真(非0值),还是为假(0值).如果逻辑表达式的值无法确定,则其计算结果为NULL

运算符          语法                含义
and,&&         a and b ,a && b     逻辑与
or,||          a or b,a||b         逻辑或
xor            a xor b             逻辑异或.有且仅有一个操作数为真
not,!          not a,!a            逻辑非


MySQL还支持运算符and or 和not的替代形式,即&&,||,!, 其用法与C语言里的一样.需要特别注意运算符||.标准SQL把||规定为字符串的连接运算符,但在MySQL里它表示的却是逻辑or运算.如果你在使用下面的表达时,期望它会执行字符串的连接,你会发现,其返回值为0.

'abc' || 'def'


之所以会发生这种情况是因为’abc’和’def’在进行运算时都被转换成了整数,即都会转换为0.

在MySQL里,必须使用concat(‘abc’,’def’)或其他办法来连接字符串.

如果想让 ’ || ’ 具有标准SQL的行为,则必须启用SQL的pipes_as_concat模式.

按位运算符可以完成二进制位的与,或,和异或运算.其中,最终结果的每一位,都是按两个操作数对应的二进制位,执行逻辑与,逻辑或,逻辑异或运算得到的.你还可以执行位的左移或右移操作.按位运算所用的值都是bigint整数值

运算符        语法             含义
&             a&b             按位与
|             a|b             按位或
^             a^b             按位异或
<<            a<<b            把a按位左移b位
>>            a>>b            把按位右移b位


比较运算符包括用于测试数字和字符串的相对大小或词法顺序的运算符,用于模式匹配的运算符,用于模式匹配的运算符,以及用于测试NULL值的运算符.其中,<=>运算符是MySQL特有的.

运算符       语法                       含义
=           a=b                        若两个操作数相等,则结果为真
<=>         a<=>b                      若两个操作数相等(即使为NULL),则结果为真
<>,!=       a<>b,a!=b                  若两个操作数不等,则结果为真
<           a<b                        若a小于b,则结果为真
<=          a<=b                       若a小于等于b,则结果为真
>=          a>=b                       若a大于等于b,则结果为真
>           a>b                        若a大于b,则结果为真
in          a in(b1,b2,,,)             若a等于b1,b2,...中的某一个,则结果为真
between     a between b and c          如果满足b<=a<=c,则结果为真
not between a not between b and c      如果不满足b<=a<=c,则结果为真
like        a like b                   SQL模式匹配.若a匹配b,则结果为真
not like    a not like b               SQL模式匹配.若a不匹配b,则结果为真
regexp      a regexp b                 正则表达式匹配.若a匹配b,则结果为真
not regexp  a not regexp b             正则表达式匹配,若a不匹配b,则结果为真
is null     a is null                  若操作数为NULL,则结果为真.
is not null a is not null              若操作数不为NULL,则结果为真


模式匹配允许我们在不指定精度字面值的情况下查找值.MySQL提供了两种类型的模式匹配.一种是利用like运算符以及通配符”%”(能匹配任意字符序列)和”_”(只能匹配单个字符)实现的SQL模式匹配.另一种是利用regexp运算符和正则表达式(它与grep,sed和vi等unix程序所使用的正则表达式很相似)实现的模式匹配.必须使用其中的一种运算符来完成模式匹配,并且不能使用=运算符.要颠倒模式匹配的含义,可以使用运算符 not like 或not regexp

这两种类型的模式匹配,除了使用的运算符和模式字符不同之外,还有以下两个重要的差异.

1.SQL的like模式只用于匹配整个字符串.正则表达式regexp可以匹配字符串的任何部分.
2.like运算符是多字节安全的.regexp运算符只能正确的处理单字节字符集,并且不会考虑排序规则.


与like运算符配合使用的模式,可以包括通配符”%”和”_”

通配符”%”能匹配任意长度的字符序列,其中包括空序列.

这意味着模式”%”能匹配任意长度的字符序列,包括空字符串.但是,’%’不能匹配NULL.事实上,其中任何一个操作数为NULL的所有模式匹配都会失败.

如果其中有一个操作数为二进制串,那么MySQL的like运算符可以把它两边的操作数当作二进制串来进行比较.如果这两个操作数都不是二进制串,那么like将根据它们的排序规则来进行比较.

'Frankly' like 'Frank%'      ->1
'frankly' like 'Frank%'      ->1
bianry 'Frankly' like 'Frank%'     ->1
binary 'frankly' like 'Frank%'     ->0
'Frankly' collate latin1_general_cs like 'Frank%'   ->1
'frankly' collate latin1_general_cs like 'Frank%'   ->0


这种行为与标准SQL的like运算符有所差异,标准SQL是区分大小写的.

like运算符的另一个通配符是下划线’-‘,他可以匹配任何单个字符.因此,模式’__‘将与任何恰好包含有三个字符的字符串相匹配.(‘_’允许自我匹配)

通配符可以指定在模式里的任何位置.

如果想匹配字符”%”或”_”本身,则 需要在其前面加上反斜线字符(“\%”或”_”),以取消其特殊含义:

'abc' like 'a%c'     ->1
'abc' like 'a\%c'    ->0
'a%c' like 'a\%c'    ->1
'abc' like 'a\c'     ->1
'abc' like 'a\_c'    ->0
'a_c' like 'a\_c'    ->1


MySQL的另一种匹配模式是使用正则表达式.运算符为regexp,而非like.ixamiande示例演示了几种比较常用的正则表达式模式匹配符.

点号运算’ . ’ 是一个可以匹配任何单个字符的通配符

方括号 ” […] ” 可以匹配列在方括号内部的任何字符

连接号 “-“(非下划线)可用于指定字符范围,其两端分别为范围的起始和结束字符.如果要把这个字符范围的含义变反(即要匹配未列在其中的字符),不那么可以在其前面加上一个”^”

’abc’  regexp ‘[a-z]’      ->1
‘abc’  regexp’[^a-z]’      ->0


星号””表示”匹配任意个其前面的字符”.例如,模式’x’将匹配任意个数的”x”字符.

‘abcdef’ regexp ‘a.*f’         ->1
‘abc’   regexp ‘[0-9]*abc’     ->1
‘abcd’ regexp ‘[0-9][0-9]*’    ->0


这里的任意个包括零个,而这也是上面第二个表达式会匹配成功的原因.

如果要匹配1个或者多个其前面的字符,则需使用’+’来代替’*’:

‘abc’ regexp ‘cd*’  ->1
‘abc’ regexp ‘cd+’  ->0
‘abcd’ regexp ‘cd+’ ->1


形如’^pattern’ 和’pattern′的模式表示的是:当pattern出现在字符串的开头或结尾时,模式匹配成功.而对于形如′patterns’的模式,只有在pattern匹配整个字符串时,才能匹配成功:

‘abc’ regexp ‘b’    ->1
‘abc’ regexp ‘^b’   ->0
‘abc’ regexp ‘b$’   ->0
‘abc’regexp ‘^abc$’ ->1
‘abcd’regexp ‘^abc$’->0


列值可以用在like或者regexp模式里,不过如果列包含了几种不同的值,那么整个匹配过程会比常量模式更慢.每当列发生变化时,模式都必须要重新检查一次,并且需要转化为内部形式.

3.5.1.2运算符优先级

当MySQL计算表达式时,其中的运算符决定了表达式中子项的分组顺序。有些运算符拥有较高的优先级,它们会先于其他运算符进行计算。例如,乘法和除法高于加法和减法的优先级。(* 和 DIV 高于 + 和 -)

下面按优先级从高到低的顺序列出了各个运算符。其中,处于同一行的运算符拥有相同的优先级。优先级高的运算符会在优先级低的运算符之前进行计算。优先级相同的运算符则按从左至右的顺序依次进行计算。

interval
binary   collate
!
-(负号) -(按位求反)
^
* / DIV % MOD
+ -
<<  >>
&
|
< <= = <=> <> != >= > in is like regexp rlike
betweeen case when then else
not
and &&
xor
or ||
:=


如果想要改变运算符的优先级,更改表达式子项的计算顺序,可以使用括号。

3.5.1.3表达式里的NULL值

在表达式里使用NULL值是,要小心,因为其结果往往会出乎你的意料。

1.当把NULL 用做算术运算符或者位运算符的操作数时,其计算结果均为NULL
2.当把NULL与逻辑运算符一起使用时,除非其计算结果可以确定,否则值均为NULL
3.当把NULL用做比较运算符或模式匹配运算符的操作数时,其计算结果均为NULL
运算符<=> 、is null和is not null例外因为他们就是用来处理NULL值的。
4.当把NULL值用作函数参数时,函数通常会返回NULL(专门处理NULL的除外)
5.在排序运算中,NULL值会一起排序.当按升序排序时,他们会出现在最前面,当以降序排序
时,会出现在最后面
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql