學習重點
通過使用邏輯運算符,可以將多個查詢條件進行組合。
通過
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;

圖 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
文氏圖
將集合(事物的聚集)的關系通過更加容易理解的圖形進行可視化展示。

圖 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
運算符能夠取出的記錄。

圖 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
運算符時需要使用括號。
四、邏輯運算符和真值
本節介紹的三個運算符 NOT
、AND
和 OR
稱為邏輯運算符。這里所說的邏輯就是對真值進行操作的意思。真值就是值為 真(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
Q1 1 1×1 1 1 0 1×0 0 0 1 0×1 0 0 0 0×0 0
OR
(邏輯和)
P Q 和 P OR
Q1 1 1+1 1 1 0 1+0 1 0 1 0+1 1 0 0 0+0 0
NOT
P 反轉 NOT
P1 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 三值邏輯中的 AND
和 OR
真值表
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
)的緣故。
請參閱
(完)