SQL 邏輯運算符


學習重點

  • 通過使用邏輯運算符,可以將多個查詢條件進行組合。

  • 通過 NOT 運算符可以生成“不是~”這樣的查詢條件。

  • 兩邊條件都成立時,使用 AND 運算符的查詢條件才成立。

  • 只要兩邊的條件中有一個成立,使用 OR 運算符的查詢條件就可以成立。

  • 值可以歸結為真(TRUE)和假(FALSE)其中之一的值稱為真值。比較運算符在比較成立時返回真,不成立時返回假。但是,在 SQL 中還存在另外一個特定的真值——不確定(UNKNOWN)。

  • 將根據邏輯運算符對真值進行的操作及其結果匯總成的表稱為真值表。

  • SQL 中的邏輯運算是包含對真、假和不確定進行運算的三值邏輯。

一、NOT 運算符

算術運算符和比較運算符 中我們介紹過,想要指定“不是~”這樣的否定條件時,需要使用 <> 運算符。除此之外還存在另外一個表示否定,並且使用范圍更廣的運算符 NOT

KEYWORD

  • NOT 運算符

NOT 不能單獨使用,必須和其他查詢條件組合起來使用。例如,選取出銷售單價(sale_price)大於等於 1000 日元的記錄的 SELECT 語句如下所示(代碼清單 30)。

代碼清單 30 選取出銷售單價大於等於 1000 日元的記錄

SELECT product_name, product_type, sale_price
  FROM Product
 WHERE sale_price >= 1000;

執行結果

 product_name  | product_type | sale_price
---------------+--------------+------------
 T恤衫         | 衣服         |       1000
 運動T恤       | 衣服         |       4000
 菜刀          | 廚房用具     |       3000
 高壓鍋        | 廚房用具     |       6800

向上述 SELECT 語句的查詢條件中添加 NOT 運算符之后的結果如下所示(代碼清單 31)。

代碼清單 31 向代碼清單 30 的查詢條件中添加 NOT 運算符

SELECT product_name, product_type, sale_price
  FROM Product
 WHERE NOT sale_price >= 1000;

執行結果

 product_name  | product_type | sale_price
---------------+--------------+-------------
 打孔器        | 辦公用品     |          500
 叉子          | 廚房用具     |          500
 擦菜板        | 廚房用具     |          880
 圓珠筆        | 辦公用品     |          100

明白了嗎?通過否定銷售單價大於等於 1000 日元(sale_price >= 1000)這個查詢條件,就可以選取出銷售單價小於 1000 日元的商品。也就是說,代碼清單 31 中 WHERE 子句指定的查詢條件,與代碼清單 32 中 WHERE 子句指定的查詢條件(sale_price < 1000)是等價的 [1](圖 5)。

代碼清單 32 WHERE 子句的查詢條件和代碼清單 31 中的查詢條件是等價的

SELECT product_name, product_type
  FROM Product
 WHERE sale_price < 1000;
使用 NOT 運算符時查詢條件的變化

圖 5 使用 NOT 運算符時查詢條件的變化

通過以上的例子大家可以發現,不使用 NOT 運算符也可以編寫出效果相同的查詢條件。不僅如此,不使用 NOT 運算符的查詢條件更容易讓人理解。使用 NOT 運算符時,我們不得不每次都在腦海中進行“大於等於 1000 日元以上這個條件的否定就是小於 1000 日元”這樣的轉換。

雖然如此,但是也不能完全否定 NOT 運算符的作用。在編寫復雜的 SQL 語句時,經常會看到 NOT 的身影。這里只是希望大家了解 NOT 運算符的書寫方法和工作原理,同時提醒大家不要濫用該運算符。

法則 10

NOT 運算符用來否定某一條件,但是不能濫用。

二、AND 運算符和 OR 運算符

到目前為止,我們看到的每條 SQL 語句中都只有一個查詢條件。但在實際使用當中,往往都是同時指定多個查詢條件對數據進行查詢的。例如,想要查詢“商品種類為廚房用具、銷售單價大於等於 3000 日元”或“進貨單價大於等於 5000 日元或小於 1000 日元”的商品等情況。

WHERE 子句中使用 AND 運算符或者 OR 運算符,可以對多個查詢條件進行組合。

KEYWORD

  • AND 運算符

  • OR 運算符

AND 運算符在其兩側的查詢條件都成立時整個查詢條件才成立,其意思相當於“並且”。

OR 運算符在其兩側的查詢條件有一個成立時整個查詢條件都成立,其意思相當於“或者” [2]

例如,從 Product 表中選取出“商品種類為廚房用具(product_type = '廚房用具'),並且銷售單價大於等於 3000 日元(sale_price >= 3000)的商品”的查詢條件中就使用了 AND 運算符(代碼清單 33)。

代碼清單 33 在 WHERE 子句的查詢條件中使用 AND 運算符

SELECT product_name, purchase_price
  FROM Product
 WHERE product_type = '廚房用具'
   AND sale_price >= 3000;

執行結果

 product_name  | purchase_price
---------------+---------------
 菜刀          |           2800
 高壓鍋        |           5000

該查詢條件的文氏圖如圖 6 所示。左側的圓圈代表符合查詢條件“商品種類為廚房用具”的商品,右側的圓圈代表符合查詢條件“銷售單價大於等於 3000 日元”的商品。兩個圓重合的部分(同時滿足兩個查詢條件的商品)就是通過 AND 運算符能夠選取出的記錄。

KEYWORD

  • 文氏圖

    將集合(事物的聚集)的關系通過更加容易理解的圖形進行可視化展示。

AND 運算符的工作效果圖

圖 6 AND 運算符的工作效果圖

選取出“商品種類為廚房用具(product_type = '廚房用具'),或者銷售單價大於等於 3000 日元(sale_price >= 3000)的商品”的查詢條件中使用了 OR 運算符(代碼清單 34)。

代碼清單 34 在 WHERE 子句的查詢條件中使用 OR 運算符

SELECT product_name, purchase_price
  FROM Product
 WHERE product_type = '廚房用具'
    OR sale_price >= 3000;

執行結果

 product_name  | purchase_price
---------------+---------------
 運動T恤       |           2800
 菜刀          |           2800
 高壓鍋        |           5000
 叉子          |
 擦菜板        |            790

還是讓我們來看看查詢條件的文氏圖吧(圖 7)。包含在左側的圓圈(商品種類為廚房用具的商品)或者右側的圓圈(銷售單價大於等於 3000 日元的商品)中的部分(兩個查詢條件中滿足任何一個的商品)就是通過 OR 運算符能夠取出的記錄。

OR 運算符的工作效果圖

圖 7 OR 運算符的工作效果圖

通過文氏圖可以方便地確認由多個條件組合而成的復雜的 SQL 語句的查詢條件,大家可以多多加以利用。

法則 11

多個查詢條件進行組合時,需要使用 AND 運算符或者 OR 運算符。

 

法則 12

文氏圖很方便。

三、通過括號強化處理

接下來我們嘗試書寫稍微復雜一些的查詢條件。例如,使用下面的查詢條件對 Product 表進行查詢的 SELECT 語句,其 WHERE 子句的條件表達式該怎么寫呢?

“商品種類為辦公用品”

並且

“登記日期是 2009 年 9 月 11 日或者 2009 年 9 月 20 日”

滿足上述查詢條件的商品(product_name)只有“打孔器”。

把上述查詢條件原封不動地寫入 WHERE 子句中,得到的 SELECT 語句似乎就可以滿足需求了(代碼清單 35)。

代碼清單 35 將查詢條件原封不動地寫入條件表達式

SELECT product_name, product_type, regist_date
  FROM Product
 WHERE product_type = '辦公用品'
   AND regist_date = '2009-09-11'
    OR regist_date = '2009-09-20';

讓我們馬上執行上述 SELECT 語句試試看,會得到下面這樣的錯誤結果。

執行結果

 product_name  | product_type | regist_date
---------------+--------------+------------
 T恤衫         | 衣服         | 2009-09-20
 打孔器        | 辦公用品     | 2009-09-11
 菜刀          | 廚房用具     | 2009-09-20
 叉子          | 廚房用具     | 2009-09-20

不想要的 T 恤衫、菜刀和叉子也被選出來了,真是頭疼呀。到底為什么會得到這樣的結果呢?

這是 AND 運算符優先於 OR 運算符所造成的。代碼清單 35 中的條件表達式會被解釋成下面這樣。

「product_type = '辦公用品' AND regist_date = '2009-09-11'」
 OR
 「regist_date = '2009-09-20'」

也就是,

“商品種類為辦公用品,並且登記日期是 2009 年 9 月 11 日”

或者

“登記日期是 2009 年 9 月 20 日”

這和想要指定的查詢條件並不相符。想要優先執行 OR 運算符時,可以像代碼清單 36 那樣使用半角括號 ()OR 運算符及其兩側的查詢條件括起來。

KEYWORD

  • ()

代碼清單 36 通過使用括號讓 OR 運算符先於 AND 運算符執行

SELECT product_name, product_type, regist_date
  FROM Product
 WHERE product_type = '辦公用品'
   AND (   regist_date = '2009-09-11'
        OR regist_date = '2009-09-20');

執行結果

 product_name  | product_type | regist_date
---------------+--------------+------------
 打孔器         | 辦公用品     | 2009-09-11

這樣就選取出了想要得到的“打孔器”。

法則 13

AND 運算符的優先級高於 OR 運算符。想要優先執行 OR 運算符時需要使用括號。

四、邏輯運算符和真值

本節介紹的三個運算符 NOTANDOR 稱為邏輯運算符。這里所說的邏輯就是對真值進行操作的意思。真值就是值為 真(TRUE假(FALSE 其中之一的值 [3]

KEYWORD

  • 邏輯運算符

  • 真值

  • 真(TRUE

  • 假(FALSE

算術運算符和比較運算符 中介紹的比較運算符會把運算結果以真值的形式進行返回。比較結果成立時返回真(TRUE),比較結果不成立時返回假(FALSE[4]。例如,對於 purchase_price >= 3000 這個查詢條件來說,由於 product_name 列為 '運動 T 恤' 的記錄的 purchase_price 列的值是 2800,因此會返回假(FALSE),而 product_name 列為 '高壓鍋' 的記錄的 purchase_price 列的值是 5000,所以返回真(TRUE)。

邏輯運算符對比較運算符等返回的真值進行操作。AND 運算符兩側的真值都為真時返回真,除此之外都返回假。OR 運算符兩側的真值只要有一個不為假就返回真,只有當其兩側的真值都為假時才返回假。NOT 運算符只是單純的將真轉換為假,將假轉換為真。真值表(truth table)就是對這類操作及其結果進行的總結(表 4)。

KEYWORD

  • 真值表

表 4 真值表

AND

P Q P AND Q

OR

P Q P OR Q

NOT

P NOT P

請將表 4 中的 P 和 Q 想象為“銷售單價為 500 日元”這樣的條件。邏輯運算的結果只有真和假兩種,對其進行排列組合將會得到 2 × 2 = 4 種結果。

SELECT 語句的 WHERE 子句中,通過 AND 運算符將兩個查詢條件連接起來時,會查詢出這兩個查詢條件都為真的記錄。通過 OR 運算符將兩個查詢條件連接起來時,會查詢出某一個查詢條件為真或者兩個查詢條件都為真的記錄。在條件表達式中使用 NOT 運算符時,會選取出查詢條件為假的記錄(反過來為真)。

雖然表 4 中的真值表只是使用一個邏輯運算符時得到的結果,但即使使用兩個以上的邏輯運算符連接三個以上的查詢條件,通過反復進行邏輯運算求出真值,不論多復雜的條件也可以得到相應的結果。

表 5 就是根據之前例子中的查詢條件“商品種類為辦公用品”,並

且“登記日期是 2009 年 9 月 11 日或者 2009 年 9 月 20 日”(product_type = ' 辦公用品 ' AND (regist_date = '2009-09-11' OR regist_date = '2009-09-20'))做成的真值表。

表 5 查詢條件為 P AND(Q OR R)的真值表

P AND (Q OR R)

P Q R Q OR R P AND (Q OR R)

P :商品種類為辦公用品

Q :登記日期是 2009 年 9 月 11 日

R :登記日期是 2009 年 9 月 20 日

Q OR R :登記日期是 2009 年 9 月 11 日或者 2009年9月20日

P AND (Q OR R):商品種類為辦公用品,並且,登記日期是 2009 年 9 月 11 日或者 2009 年 9 月 20 日

代碼清單 36 中的 SELECT 語句,查詢出了唯一滿足 P AND(Q OR R) 為真的記錄“打孔器”。

法則 14

通過創建真值表,無論多復雜的條件,都會更容易理解。

專欄

邏輯積與邏輯和

將表 4 的真值表中的真變為 1、假變為 0,意外地得到了下述規則。

表 A 真為 1、假為 0 的真值表

AND(邏輯積)

P Q P AND Q
1 1 1×1 1
1 0 1×0 0
0 1 0×1 0
0 0 0×0 0

OR(邏輯和)

P Q P OR Q
1 1 1+1 1
1 0 1+0 1
0 1 0+1 1
0 0 0+0 0

NOT

P 反轉 NOT P
1 1 → 0 0
0 0 → 1 1

NOT 運算符並沒有什么特別的改變,但是 AND 運算的結果與乘法運算(積),OR 運算的結果與加法運算(和)的結果卻是一樣的 [5]。因此,使用 AND 運算符進行的邏輯運算稱為邏輯積,使用 OR 運算符進行的邏輯運算稱為邏輯和

KEYWORD

  • 邏輯積

  • 邏輯和

五、含有 NULL 時的真值

算術運算符和比較運算符 中我們介紹了查詢 NULL 時不能使用比較運算符(= 或者 <>),需要使用 IS NULL 運算符或者 IS NOT NULL 運算符。實際上,使用邏輯運算符時也需要特別對待 NULL

我們來看一下 Product(商品)表,商品“叉子”和“圓珠筆”的進貨單價(purchase_price)為 NULL。那么,對這兩條記錄使用查詢條件 purchase_price = 2800(進貨單價為 2800 日元)會得到什么樣的真值呢?如果結果為真,則通過該條件表達式就可以選取出“叉子”和“圓珠筆”這兩條記錄。但是在之前介紹“不能對 NULL 使用比較運算符”(算術運算符和比較運算符)時,我們就知道結果並不是這樣的,也就是說結果不為真。

那結果會為假嗎?實際上結果也不是假。如果結果為假,那么對其進行否定的條件 NOT purchase_price = 2800(進貨單價不是 2800 日元)的結果應該為真,也就能選取出這兩條記錄了(因為假的對立面為真),但實際結果卻並不是這樣。

既不是真也不是假,那結果到底是什么呢?其實這是 SQL 中特有的情況。這時真值是除真假之外的第三種值——不確定(UNKNOWN。一般的邏輯運算並不存在這第三種值。SQL 之外的語言也基本上只使用真和假這兩種真值。與通常的邏輯運算被稱為二值邏輯相對,只有 SQL 中的邏輯運算被稱為三值邏輯

KEYWORD

  • 不確定

  • 二值邏輯

  • 三值邏輯

因此,表 4 中的真值表並不完整,完整的真值表應該像表 6 這樣包含“不確定”這個值。

表 6 三值邏輯中的 ANDOR 真值表

AND

P Q P AND Q
不確定 不確定
不確定
不確定 不確定
不確定
不確定 不確定 不確定

OR

P Q P OR Q
不確定
不確定 不確定
不確定
不確定 不確定
不確定 不確定 不確定

專欄

Product 表中設置 NOT NULL 約束的原因

原本只有 4 行的真值表,如果要考慮 NULL 的話就會像表 6 那樣增加為 3×3=9 行,看起來也變得更加繁瑣,考慮 NULL 時的條件判斷也會變得異常復雜,這與我們希望的結果大相徑庭。因此,數據庫領域的有識>之士們達成了“盡量不使用 NULL”的共識。

這就是為什么在創建 Product 表時要給某些列設置 NOT NULL 約束(禁止錄入 NULL)的緣故。

請參閱

(完)


  1. 判定的結果相等。 ↩︎

  2. 需要注意的是,並不是只有一個條件成立時整個查詢條件才成立,兩個條件都成立時整個查詢條件也同樣成立。這與“到場的客人可以選擇鑰匙鏈或者迷你包作為禮品 ( 任選其一 )”中的“或者”有所不同。 ↩︎

  3. 但是在 SQL 中還存在“不確定”(UNKNOWN)這樣的值。接下來會進行詳細說明。 ↩︎

  4. 算術運算符返回的結果是數字。除了返回結果的類型不同之外,和比較運算符一樣都會返回運算結果。 ↩︎

  5. 嚴格來說,此處的 1+1=1 與通常的整數運算並不相同。只是因為真值中只存在 0 和 1 兩種情況,所以才有了這樣的結果。 ↩︎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM