《SQL必知必会》笔记3-过滤where、and、or、in、通配符

1 过滤检索数据(WHERE)

1.1 使用WHERE子句

SELECT prod_name, prod_price 
FROM Products
WHERE prod_price = 3.49;

WHERE子句指定对搜索条件进行过滤。

注意:在同时使用ORDER BY和WHERE子句时,应该让ORDER BY位于WHERE之后,否则会产生错误。


1.2 WHERE子句操作符

操作符 说明
= 等于
<> 不等于
!= 不等于
< 小于
<= 小于等于
!< 不小于
> 大于
>= 大于等于
!> 不大于
BETWEEN 在指定的两个值之间
IS NULL 为NULL值

注意:表中列出的某些操作符是冗余的(如<>与!=相同,!<相当于>=),并非所有的DBMS都支持这些操作符。


1.2.1 检查单个值

列出所有价格小于10美元的产品。

SELECT prod_name, prod_price 
FROM Products
WHERE prod_price < 10;

1.2.2 不匹配检查

列出所有不是供应商DLL01制造的产品。

SELECT vend_id, prod_name 
FROM Products
WHERE vend_id <> 'DLL01';

SELECT vend_id, prod_name
FROM Products
WHERE vend_id != 'DLL01';

如果将值与字符串类型的列进行比较,就需要限定引号。用来与数值列进行比较的值不用引号。

!=和<>通常可以互换,但是并非所有DBMS都支持这两种不等于操作符。


1.2.3 范围值检查

要检查某个范围的值,可以使用BETWEEN操作符。例如:BETWEEN操作符可用来检索价格在5美元和10美元之间的所有产品,或在指定的开始日期和结束日期之间的所有日期。

检索价格在5美元和10美元之间的所有产品。

SELECT prod_name, prod_price 
FROM Products
WHERE prod_price BETWEEN 5 AND 10;

在使用BETWEEN时,必须指定两个值——所需范围的低端值和高端值。这两个值必须用AND关键字分隔,BETWEEN匹配范围中所有的值,包括指定的开始值和结束值。


1.2.4 空值检查

在创建表时,表设计人员可以指定其中的列能否不包含值。在一个列不包含值时,称其包含空值NULL。
NULL:无值(no value),它与字段包含0、空字符串或仅仅包含空格不同。

SELECT cust_name 
FROM Customers 
WHERE cust_email IS NULL;

通过过滤选择不包含指定值的所有行时,你可能希望返回含NULL值的行。但是做不到,因为未知(unknown)有特殊的含义,数据库不知道它们是否匹配,所以在进行匹配过滤或非匹配过滤时,不会返回这些结果。

过滤数据时,一定要验证被过滤列中含NULL的行确实出现在返回的数据中。


2 高级数据过滤(AND、OR、IN、NOT IN)

2.1 组合WHERE子句

操作符:用来联结或改变WHERE子句中的子句的关键字,也称为逻辑操作符(logical operator)。

2.1.1 AND操作符

要通过不止一个列进行过滤,可以使用AND操作符给WHERE子句附加条件。

SELECT prod_id, prod_price, prod_name 
FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4;

SELECT prod_id, prod_price, prod_name 
FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4
ORDER BY prod_name;

这个例子只包含一个AND子句,因此最多有两个过滤条件。可以增加多个过滤条件,每个条件间都要使用AND关键字。


2.1.2 OR操作符

许多DBMS在OR WHERE子句的第一个条件得到满足的情况下,就不再计算第二个条件了(在第一个条件满足时,不管第二个条件是否满足,相应的行都将被检索出来)。

SELECT prod_name, prod_price 
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01';

2.1.3 求值顺序(AND、OR)

WHERE子句可以包含任意数目的AND和OR操作符,允许两者结合以进行复杂、高级的过滤。

假如需要列出价格为10美元及以上,且由DLL01或BRS01制造的所有产品。

SELECT prod_name, prod_price 
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01'
      AND prod_price >= 10;

相当于:

SELECT prod_name, prod_price 
FROM Products
WHERE vend_id = 'DLL01' OR (vend_id = 'BRS01'
      AND prod_price >= 10);

返回的行中有4行价格小于10美元,显然返回的行未按预期的进行过滤。为什么会这样呢?原因在于求值的顺序。SQL在处理OR操作符前,优先处理AND操作符。

当SQL看到上述WHERE子句时,它理解为:由供应商BRS01制造的价格为10美元以上的所有产品,以及由供应商DLL01制造的所有产品,而不管其价格如何。换句话说,由于AND在求值过程中优先级更高,操作符被错误地组合了。

使用圆括号对操作符进行明确分组。

SELECT prod_name, prod_price 
FROM Products
WHERE (vend_id = 'DLL01' OR vend_id = 'BRS01')
      AND prod_price >= 10;

这条SELECT语句与前一条的唯一差别是,将前两个条件用圆括号括了起来。因为圆括号具有比AND或OR操作符更高的求值顺序,所以DBMS首先过滤圆括号内的OR条件。这时,SQL语句变成了选择由供应商DLL01或BRS01制造的且价格在10美元及以上的所有产品,这正是我们希望的结果。


建议:任何时候使用具有AND和OR操作符的WHERE子句,都应该使用圆括号明确地分组操作符。


2.2 IN操作符

IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。IN取一组由逗号分隔、括在圆括号中的合法值。

检索由供应商DLL01和BRS01制造的所有产品。

下面先使用IN操作符:

SELECT prod_name, prod_price 
FROM Products
WHERE vend_id IN ('DLL01', 'BRS01')
ORDER BY prod_name;

下面使用OR操作符:

SELECT prod_name, prod_price 
FROM Products
WHERE vend_id = 'DLL01' OR vend_id ='BRS01'
ORDER BY prod_name;

由上可以看出IN操作符完成了与OR相同的功能。

为什么要使用IN操作符?其优点如下:

  1. 在有很多合法选项时,IN操作符的语法更清楚,更直观。
  2. 在与其他AND和OR操作符组合使用IN时,求值顺序更容易管理。
  3. IN操作符一般比一组OR操作符执行得更快(在上面这个合法选项很少的例子中,你看不出来性能差异)。
  4. IN的最大优点是可以包含其他SELECT语句,能够更动态地建立WHERE子句。

2.3 NOT操作符

NOT操作符有且只有一个功能,那就是否定其后所跟的任何条件。因为NOT从不单独使用(它总是与其他操作符一起使用),所以它的语法与其他操作符有所不同。

NOT关键字可以用在要过滤的列前,而不仅是在其后。

列出除DLL01之外的所有供应商制造的产品。

SELECT prod_name 
FROM Products
WHERE NOT vend_id = 'DLL01'
ORDER BY prod_name;

也可用<>操作符来完成。

SELECT prod_name 
FROM Products
WHERE vend_id <> 'DLL01'
ORDER BY prod_name;

为什么使用NOT?

对于这里的这种简单的WHERE子句,使用NOT确实没有什么优势,但在更复杂的子句中,NOT是非常有用的。例如,在与IN操作符联合使用时,NOT可以非常简单地找出与条件列表不匹配的行。


3 用通配符进行过滤(LIKE、%、_、[])

3.1 LIKE操作符

怎样搜索产品名中包含文本bean bag的所有产品?用简单的比较操作符肯定不行,必须使用通配符。

利用通配符,可以创建比较特定数据的搜索模式。在这个例子中,如果你想找出名称包含bean bag的所有产品,可以构造一个通配符搜索模式,找出在产品名的任何位置出现bean bag的产品。

通配符(wildcard):用来匹配值的一部分的特殊字符。

搜索模式(search pattern):由字面值、通配符或两者组合构成的搜索条件。

通配符本身实际上是SQL的WHERE子句中有特殊含义的字符,SQL支持几种通配符。为在搜索子句中使用通配符,必须使用LIKE操作符。

通配符搜索只能用于文本字段(字符串),非文本数据类型字段不能使用通配符搜索。

3.1.1 百分号(%)通配符

在搜索串中,%表示任何字符出现任意次数。

找到所有以词Fish起头的产品。

SELECT prod_id, prod_name 
FROM Products
WHERE prod_name LIKE 'Fish%';

通配符可在搜索模式中的任何位置使用,并且可以使用多个通配符。

SELECT prod_id, prod_name 
FROM Products
WHERE prod_name LIKE '%bean bag%';

找出以F起头、以y结尾的所有产品。

SELECT prod_id, prod_name 
FROM Products
WHERE prod_name LIKE 'F%y';

简单的解决办法是给搜索模式再增加一个%号:'F%y'还匹配y之后的字符(或空格),更好的办法解决办法是用函数去掉空格。

通配符%看起来像是可以匹配任何东西,但有个例外,这就是NULL。子句WHERE prod_name LIKE '%'不会匹配产品名称为NULL的行。


3.1.2 下划线(_)通配符

_只匹配单个字符,而不是多个字符。

SELECT prod_id, prod_name 
FROM Products
WHERE prod_name LIKE '__ inch teddy bear';

SELECT prod_id, prod_name 
FROM Products
WHERE prod_name LIKE '% inch teddy bear';

3.1.3 方括号([])通配符

方括号([])通配符用来指定一个字符集,它必须匹配指定位置(通配符的位置)的一个字符。

此查询只支持Access和SQL Server,不支持MySQL数据库。

找出所有名字以J或M起头的联系人。

SELECT cust_contact 
FROM Customers
WHERE cust_contact LIKE '[JM]%'
ORDER BY cust_contact;

输出结果为:

Jim Jones
John Smith
Michelle Green

3.2 使用通配符的技巧

  1. 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
  2. 在确实需要使用通配符时,尽量不要把它们用在搜索模式的开始处。把通配符置于开始处,搜素起来是最慢的。
  3. 仔细注意通配符的位置。如果放错位置,可能不会返回想要的数据。

如果您发现文中有不清楚或者有问题的地方,请在下方评论区留言,我会根据您的评论,更新文中相关内容,谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容

  • 数据库入门 数据库: 保存有组织的数据的容器(通常是一个文件或一组文件).数据库软件应该称为 DBMS(DataB...
    Mjericho阅读 470评论 0 0
  • 注:这一系列的文章是《SQL必知必会》第四版的读书笔记。 1.了解SQL 1.1 数据库基础 数据库:保存有组织的...
    zuyuxia阅读 561评论 0 0
  • 这篇文章主要是讨论通过组合WHERE子句来建立功能更强,更高级的搜索条件,其中包括NOT和IN操作符 此前我们讲过...
    CoolForrest阅读 337评论 0 1
  • 不自信的五个可能原因: 1.古老的古人,面对自然的无力和无知,诞生了对自然和万物的崇敬与畏惧,敬天尊地,人只是万物...
    崇德先生阅读 1,707评论 0 7
  • 我是日记星球213号星宝宝秀兰,正在参加孙老师的日记星球21天蜕变之的写作训练,这是我的第44篇原创日记。 你看或...
    雨珺阅读 217评论 2 3