算术运算符和比较运算符
算术运算符 SQL语句中可以使用计算表达式。用SELECT语句,把各个商品单价的2倍(sale_price的2倍)以"sale_price_x2"列的形式读取出来。 SQL语句中也可以使用运算表达式
执行结果 sale_price_x2列中的sale_price * 2就是计算销售单价的2倍的表达式。以product_name列的值为’T恤衫’的记录行为例,sale_price列的值1000的2倍是2000,它以sale_price_x2列的形式被查询出来。同样,’打孔器’记录行的值500的2倍1000,'运动T恤’记录行的值4000的2倍8000,都被查询出来了。运算就是这样以行为单位执行的。 SQL语句中可以使用的四则运算的主要运算符 四则运算所使用的运算符(+、-、*、/)称为算术运算符。运算符就是使用其两边的值进行四则运算或者字符串拼接、数值大小比较等运算,并返回结果的符号。加法运算符(+)前后如果是数字或者数字类型的列名的话,就会返回加法运算后的结果。SQL中除了算术运算符之外还有其他各种各样的运算符。
当然,SQL中也可以像平常的运算表达式那样使用括号( )。括号中运算表达式的优先级会得到提升,优先进行运算。例如在运算表达式(1+2)* 3中,会先计算1+2的值,然后再对其结果进行* 3运算。 括号的使用并不仅仅局限于四则运算,还可以用在SQL语句的任何表达式当中。 需要注意NULL SQL语句中进行运算时,需要特别注意含有NULL的运算。请大家考虑一下在SQL语句中进行如下运算时,结果会是什么呢? A.5+NULL B.10- NULL C. 1 * NULL D.4 / NULL E.NULL / 9 F.NULL / 0 正确答案全部都是NULL。大家可能会觉得奇怪,为什么会这样呢?实际上所有包含NULL的计算,结果肯定是NULL。即使像F那样用NULL除以0时这一原则也适用。通常情况下,类似5/0这样除数为0的话会发生错误,只有NULL除以0时不会发生错误,并且结果还是NULL。 尽管如此,很多时候我们还是希望NULL能像0一样,得到5+NULL=5这样的结果。不过也不要紧,SQL中也为我们准备了可以解决这类情况的方法.
比较运算符 下面让我们再使用符号=选取出销售单价(sale_price)为500日元(数字500)的记录 选取出sale_price列为500的记录
执行结果
像符号=这样用来比较其两边的列或者值的符号称为比较运算符,符号=就是比较运算符。在WHERE子句中通过使用比较运算符可以组合出各种各样的条件表达式. 接下来,我们使用“不等于”这样代表否定含义的比较运算符<>,选取出sale_price列的值不为500的记录:
执行结果 SQL中主要的比较运算符如表2-2所示,除了等于和不等于之外,还有进行大小比较的运算符。 这些比较运算符可以对字符、数字和日期等几乎所有数据类型的列和值进行比较。例如,从Product表中选取出销售单价(sale_price)大于等于1000日元的记录,或者登记日期(regist_date)在2009年9月27日之前的记录,可以使用比较运算符>=和<,在WHERE子句中生成如下条件表达式. 选取出销售单价大于等于1000日元的记录
执行结果 选取出登记日期在2009年9月27日之前的记录
执行结果 小于某个日期就是在该日期之前的意思。想要实现在某个特定日期(包含该日期)之后的查询条件时,可以使用代表大于等于的>=运算符。 另外,在使用大于等于(>=)或者小于等于(<=)作为查询条件时,一定要注意不等号(<、>)和等号(=)的位置不能颠倒。一定要让不等号在左,等号在右。如果写成(=<)或者(=>)就会出错。当然,代表不等于的比较运算符也不能写成(><)。
除此之外,还可以使用比较运算符对计算结果进行比较。代码清单2-22在WHERE子句中指定了销售单价(sale_price)比进货单价(purchase_price)高出500日元以上的条件表达式。为了判断是否高出500日元,需要用sale_price列的值减去purchase_price列的值。 WHERE子句的条件表达式中也可以使用计算表达式
执行结果 对字符串使用不等号时的注意事项 对字符串使用大于等于或者小于等于不等号时会得到什么样的结果呢? 接下来我们使用Chars表来进行确认。虽然该表中存储的都是数字,但chr是字符串类型(CHAR类型)的列。
插入数据
选取出大于’2’的数据的SELECT语句
执行结果
没想到吧?是不是觉得10和11比2大,所以也应该选取出来呢?大家之所以这样想,是因为混淆了数字和字符串,也就是说2和’2’并不一样。 现在,chr列被定为字符串类型,并且在对字符串类型的数据进行大小比较时,使用的是和数字比较不同的规则。典型的规则就是按照字典顺序进行比较,也就是像姓名那样,按照条目在字典中出现的顺序来进行排序。该规则最重要的一点就是,以相同字符开头的单词比不同字符开头的单词更相近。 Chars表chr列中的数据按照字典顺序进行排序的结果如下所示。 1 10 11 2 222 3 '10’和’11’同样都是以’1’开头的字符串,首先判定为比’2’小。这就像在字典中“提问”“提议”和“问题”按照如下顺序排列一样。 提问 提议 问题 进行大小比较时,得到的结果是’1-3’比’2’小('1-3'<'2'), '3’大于’2-2'('3' > '2')。 比较字符串类型大小的规则今后还会经常使用,所以请大家牢记.
不能对NULL使用比较运算符 关于比较运算符还有一点十分重要,那就是作为查询条件的列中含有NULL的情况。例如,我们把进货单价(purchase_price)作为查询条件。请注意,商品“叉子”和“圆珠笔”的进货单价是NULL。 我们先来选取进货单价为2800日元(purchase_price=2800)的记录。
执行结果 大家对这个结果应该都没有疑问吧?接下来我们再尝试选取出进货单价不是2800日元(purchase_price <> 2800)的记录.
执行结果 执行结果中并没有“叉子”和“圆珠笔”。这两条记录由于进货单价不明(NULL),因此无法判定是不是2800日元。 那如果想选取进货单价为NULL的记录的话,条件表达式该怎么写呢?历经一番苦思冥想后,用“purchase_price=NULL”试了试,还是一条记录也取不出来。 即使使用<>运算符也还是无法选取出NULL的记录。因此,SQL提供了专门用来判断是否为NULL的IS NULL运算符。想要选取NULL的记录时,可以像这样来书写条件表达式。
执行结果 反之,希望选取不是NULL的记录时,需要使用IS NOT NULL运算符.
执行结果
逻辑运算符
NOT运算符 想要指定“不是~”这样的否定条件时,需要使用<>运算符。除此之外还存在另外一个表示否定,并且使用范围更广的运算符NOT。 NOT不能单独使用,必须和其他查询条件组合起来使用。例如,选取出销售单价(sale_price)大于等于1000日元的记录的SELECT语句如下所示
执行结果 查询条件中添加NOT运算符
执行结果 明白了吗?通过否定销售单价大于等于1000日元(sale_price>= 1000)这个查询条件,就可以选取出销售单价小于1000日元的商品。也就是说,WHERE子句指定的查询条件,与代码清单2-32中WHERE子句指定的查询条件(sale_price < 1000)是等价的.
使用NOT运算符时查询条件的变化 通过以上的例子大家可以发现,不使用NOT运算符也可以编写出效果相同的查询条件。不仅如此,不使用NOT运算符的查询条件更容易让人理解。使用NOT运算符时,我们不得不每次都在脑海中进行“大于等于1000日元以上这个条件的否定就是小于1000日元”这样的转换。 虽然如此,但是也不能完全否定NOT运算符的作用。在编写复杂的SQL语句时,经常会看到NOT的身影。这里只是希望大家了解NOT运算符的书写方法和工作原理,同时提醒大家不要滥用该运算符。
到目前为止,我们看到的每条SQL语句中都只有一个查询条件。但在实际使用当中,往往都是同时指定多个查询条件对数据进行查询的。例如,想要查询“商品种类为厨房用具、销售单价大于等于3000日元”或“进货单价大于等于5000日元或小于1000日元”的商品等情况。 在WHERE子句中使用AND运算符或者OR运算符,可以对多个查询条件进行组合。 AND运算符在其两侧的查询条件都成立时整个查询条件才成立,其意思相当于“并且”。 OR运算符在其两侧的查询条件有一个成立时整个查询条件都成立,其意思相当于“或者”. 例如,从Product表中选取出“商品种类为厨房用具(product_type=’厨房用具’),并且销售单价大于等于3000日元(sale_price >= 3000)的商品”的查询条件中就使用了AND运算符.
执行结果 左侧的圆圈代表符合查询条件“商品种类为厨房用具”的商品,右侧的圆圈代表符合查询条件“销售单价大于等于3000日元”的商品。两个圆重合的部分(同时满足两个查询条件的商品)就是通过AND运算符能够选取出的记录。 将集合(事物的聚集)的关系通过更加容易理解的图形进行可视化展示。 选取出“商品种类为厨房用具(product_type=’厨房用具’),或者销售单价大于等于3000日元(sale_price >=3000)的商品”的查询条件中使用了OR运算符.
执行结果 还是让我们来看看查询条件的文氏图吧!包含在左侧的圆圈(商品种类为厨房用具的商品)或者右侧的圆圈(销售单价大于等于3000日元的商品)中的部分(两个查询条件中满足任何一个的商品)就是通过OR运算符能够取出的记录。 通过文氏图件,大家可以多多加以利用。可以方便地确认由多个条件组合而成的复杂的SQL语句的查询条.
通过括号强化处理 接下来我们尝试书写稍微复杂一些的查询条件。例如,使用下面的查询条件对Product表进行查询的SELECT语句,其WHERE子句的条件表达式该怎么写呢? 商品种类为办公用品”并且“登记日期是2009年9月11日或者2009年9月20日”满足上述查询条件的商品(product_name)只有“打孔器”。 把上述查询条件原封不动地写入WHERE子句中,得到的SELECT语句似乎就可以满足需求了.
执行结果 不想要的T恤衫、菜刀和叉子也被选出来了,真是头疼呀。到底为什么会得到这样的结果呢?这是AND运算符优先于OR运算符所造成的。 这和想要指定的查询条件并不相符。想要优先执行OR运算符时,可以使用半角括号( )将OR运算符及其两侧的查询条件括起来。
执行结果 这样就选取出了想要得到的“打孔器”。
逻辑运算符和真值 逻辑运算符对比较运算符等返回的真值进行操作。AND运算符两侧的真值都为真时返回真,除此之外都返回假。OR运算符两侧的真值只要有一个不为假就返回真,只有当其两侧的真值都为假时才返回假。NOT运算符只是单纯的将真转换为假,将假转换为真。真值表(truth table)就是对这类操作及其结果进行的总结. 在SELECT语句的WHERE子句中,通过AND运算符将两个查询条件连接起来时,会查询出这两个查询条件都为真的记录。通过OR运算符将两个查询条件连接起来时,会查询出某一个查询条件为真或者两个查询条件都为真的记录。在条件表达式中使用NOT运算符时,会选取出查询条件为假的记录(反过来为真)。 真值表只是使用一个逻辑运算符时得到的结果,但即使使用两个以上的逻辑运算符连接三个以上的查询条件,通过反复进行逻辑运算求出真值,不论多复杂的条件也可以得到相应的结果。 根据之前例子中的查询条件“商品种类为办公用品”,并且“登记日期是2009年9月11日或者2009年9月20日”(product_type=’办公用品’ AND(regist_date='2009-09-11' OR regist_date='2009-09-20'))做成的真值表。
NOT运算符并没有什么特别的改变,但是AND运算的结果与乘法运算(积), OR运算的结果与加法运算(和)的结果却是一样的。因此,使用AND运算符进行的逻辑运算称为逻辑积,使用OR运算符进行的逻辑运算称为逻辑和。 含有NULL时的真值 我们来看一下Product(商品)表,商品“叉子”和“圆珠笔”的进货单价(purchase_price)为NULL。那么,对这两条记录使用查询条件purchase_price=2800(进货单价为2800日元)会得到什么样的真值呢?如果结果为真,则通过该条件表达式就可以选取出“叉子”和“圆珠笔”这两条记录。但是在之前介绍“不能对NULL使用比较运算符”. 那结果会为假吗?实际上结果也不是假。如果结果为假,那么对其进行否定的条件NOT purchase_price=2800(进货单价不是2800日元)的结果应该为真,也就能选取出这两条记录了(因为假的对立面为真),但实际结果却并不是这样。 既不是真也不是假,那结果到底是什么呢?其实这是SQL中特有的情况。这时真值是除真假之外的第三种值——不确定(UNKNOWN)。一般的逻辑运算并不存在这第三种值。SQL之外的语言也基本上只使用真和假这两种真值。与通常的逻辑运算被称为二值逻辑相对,只有SQL中的逻辑运算被称为三值逻辑。
练习题 编写一条SQL语句,从Product(商品)表中选取出“登记日期(regist_date)在2009年4月28日之后”的商品。查询结果要包含product_name和regist_date两列。 请说出对Product表执行如下3条SELECT语句时的返回结果。
|
|