學習重點
運算符就是對其兩邊的列或者值進行運算(計算或者比較大小等)的符號。
使用算術運算符可以進行四則運算。
括號可以提升運算的優先順序(優先進行運算)。
包含
NULL的運算,其結果也是NULL。比較運算符可以用來判斷列或者值是否相等,還可以用來比較大小。
判斷是否為
NULL,需要使用IS NULL或者IS NOT NULL運算符。
一、算術運算符
SQL 語句中可以使用計算表達式。代碼清單 17 中的 SELECT 語句,把各個商品單價的 2 倍(sale_price 的 2 倍)以 "sale_price_x2" 列的形式讀取出來。
代碼清單 17 SQL語句中也可以使用運算表達式
SELECT product_name, sale_price,
sale_price * 2 AS "sale_price_x2"
FROM Product;
執行結果
product_name | sale_price | sale_price_x2
---------------+-------------+----------------
T恤衫 | 1000 | 2000
打孔器 | 500 | 1000
運動T恤 | 4000 | 8000
菜刀 | 3000 | 6000
高壓鍋 | 6800 | 13600
叉子 | 500 | 1000
擦菜板 | 880 | 1760
圓珠筆 | 100 | 200
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 語句中可以使用的四則運算的主要運算符如表 1 所示。
表 1 SQL 語句中可以使用的四則運算的主要運算符
| 含義 | 運算符 |
|---|---|
| 加法運算 | + |
| 減法運算 | - |
| 乘法運算 | * |
| 除法運算 | / |
KEYWORD
+運算符
-運算符
*運算符
/運算符
四則運算所使用的運算符(+、-、*、/)稱為算術運算符。運算符就是使用其兩邊的值進行四則運算或者字符串拼接、數值大小比較等運算,並返回結果的符號。加法運算符(+)前后如果是數字或者數字類型的列名的話,就會返回加法運算后的結果。SQL 中除了算術運算符之外還有其他各種各樣的運算符。
KEYWORD
算術運算符
運算符
法則 6
SELECT子句中可以使用常數或者表達式。
當然,SQL 中也可以像平常的運算表達式那樣使用括號 ()。括號中運算表達式的優先級會得到提升,優先進行運算。例如在運算表達式 (1 + 2) * 3 中,會先計算 1 + 2 的值,然后再對其結果進行 * 3 運算。
KEYWORD
()
括號的使用並不僅僅局限於四則運算,還可以用在 SQL 語句的任何表達式當中。具體的使用方法今后會慢慢介紹給大家。
二、需要注意 NULL
像代碼清單 17 那樣,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 中也為我們准備了可以解決這類情況的方法(將會在 各種各樣的函數 中進行介紹)。
專欄
FROM 子句真的有必要嗎?
在 SELECT 語句基礎 中我們介紹過
SELECT語句是由SELECT子句和FROM子句組成的。可實際上FROM子句在SELECT語句中並不是必不可少的,只使用SELECT子句進行計算也是可以的。代碼清單 A 只包含
SELECT子句的SELECT語句-- SQL Server PostgreSQL MySQL SELECT (100 + 200) * 3 AS calculation;執行結果
calculation ------------- 900實際上,通過執行
SELECT語句來代替計算器的情況基本上是不存在的。不過在極少數情況下,還是可以通過使用沒有FROM子句的SELECT語句來實現某種業務的。例如,不管內容是什么,只希望得到一行臨時數據的情況。但是也存在像 Oracle 這樣不允許省略
SELECT語句中的FROM子句的 RDBMS,請大家注意 [1]。
三、比較運算符
在 SELECT 語句基礎 學習 WHERE 子句時,我們使用符號 = 從 Product 表中選取出了商品種類(product_type)為字符串 '衣服' 的記錄。下面讓我們再使用符號 = 選取出銷售單價(sale_price)為 500 日元(數字 500)的記錄(代碼清單 18)。
代碼清單 18 選取出 sale_price 列為 500 的記錄
SELECT product_name, product_type
FROM Product
WHERE sale_price = 500;
執行結果
product_name | product_type
---------------+--------------
打孔器 | 辦公用品
叉子 | 廚房用具
像符號 = 這樣用來比較其兩邊的列或者值的符號稱為比較運算符,符號 = 就是比較運算符。在 WHERE 子句中通過使用比較運算符可以組合出各種各樣的條件表達式。
接下來,我們使用“不等於”這樣代表否定含義的比較運算符 <> [2],選取出 sale_price 列的值不為 500 的記錄(代碼清單 19)。
KEYWORD
比較運算符
=運算符
<>運算符
代碼清單 19 選取出 sale_price 列的值不是 500 的記錄
SELECT product_name, product_type
FROM Product
WHERE sale_price <> 500;
執行結果
product_name | product_type
---------------+--------------
T恤衫 | 衣服
運動T恤 | 衣服
菜刀 | 廚房用具
高壓鍋 | 廚房用具
擦菜板 | 廚房用具
圓珠筆 | 辦公用品
SQL 中主要的比較運算符如表 2 所示,除了等於和不等於之外,還有進行大小比較的運算符。
表 2 比較運算符
| 運算符 | 含義 |
|---|---|
= |
和 ~ 相等 |
<> |
和 ~ 不相等 |
>= |
大於等於 ~ |
> |
大於 ~ |
<= |
小於等於 ~ |
< |
小於 ~ |
KEYWORD
=運算符
<>運算符
>=運算符
>運算符
<=運算符
<運算符
這些比較運算符可以對字符、數字和日期等幾乎所有數據類型的列和值進行比較。例如,從 Product 表中選取出銷售單價(sale_price) 大於等於 1000 日元的記錄,或者登記日期(regist_date)在 2009 年 9 月 27 日之前的記錄,可以使用比較運算符 >= 和 <,在 WHERE 子句中生成如下條件表達式(代碼清單 20、代碼清單 21)。
代碼清單 20 選取出銷售單價大於等於 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
代碼清單 21 選取出登記日期在 2009 年 9 月27日 之前的記錄
SELECT product_name, product_type, regist_date
FROM Product
WHERE regist_date < '2009-09-27';
執行結果
product_name | product_type | regist_date
---------------+--------------+-----------
T恤衫 | 衣服 | 2009-09-20
打孔器 | 辦公用品 | 2009-09-11
菜刀 | 廚房用具 | 2009-09-20
高壓鍋 | 廚房用具 | 2009-01-15
叉子 | 廚房用具 | 2009-09-20
擦菜板 | 廚房用具 | 2008-04-28
小於某個日期就是在該日期之前的意思。想要實現在某個特定日期(包含該日期)之后的查詢條件時,可以使用代表大於等於的 >= 運算符。
另外,在使用大於等於(>=)或者小於等於(<=)作為查詢條件時,一定要注意不等號(<、>)和等號(=)的位置不能顛倒。一定要讓不等號在左,等號在右。如果寫成(=<)或者(=>)就會出錯。當然,代表不等於的比較運算符也不能寫成(><)。
法則 7
使用比較運算符時一定要注意不等號和等號的位置。
除此之外,還可以使用比較運算符對計算結果進行比較。代碼清單 22 在 WHERE 子句中指定了銷售單價(sale_price)比進貨單價(purchase_price)高出 500 日元以上的條件表達式。為了判斷是否高出 500 日元,需要用 sale_price 列的值減去 purchase_price 列的值。
代碼清單 22 WHERE 子句的條件表達式中也可以使用計算表達式
SELECT product_name, sale_price, purchase_price
FROM Product
WHERE sale_price - purchase_price >= 500;
執行結果
product_name | sale_price | purchase_price
---------------+-------------+---------------
T恤衫 | 1000 | 500
運動T恤 | 4000 | 2800
高壓鍋 | 6800 | 5000
四、對字符串使用不等號時的注意事項
對字符串使用大於等於或者小於等於不等號時會得到什么樣的結果呢?接下來我們使用表 3 中的 Chars 表來進行確認。雖然該表中存儲的都是數字,但 chr 是字符串類型(CHAR 類型)的列。
表 3 Chars 表
| chr(字符串類型) |
|---|
| 1 |
| 2 |
| 3 |
| 10 |
| 11 |
| 222 |
可以使用代碼清單 23 中的 SQL 語句來創建 Chars 表。
代碼清單 23 創建 Chars 表並插入數據
-- DDL :創建表
CREATE TABLE Chars
(chr CHAR(3) NOT NULL,
PRIMARY KEY (chr));
-- SQL Server PostgreSQL
-- DML :插入數據
BEGIN TRANSACTION; -------------①
INSERT INTO Chars VALUES ('1');
INSERT INTO Chars VALUES ('2');
INSERT INTO Chars VALUES ('3');
INSERT INTO Chars VALUES ('10');
INSERT INTO Chars VALUES ('11');
INSERT INTO Chars VALUES ('222');
COMMIT;
特定的 SQL
代碼清單 23 中的 DML 語句根據 DBMS 的不同而略有差異。在 MySQL 中執行該語句時,請大家把 ① 的部分改成“
START TRANSACTION;”。在 Oracle 和 DB2 中執行時不需用到 ① 的部分,請刪除。
那么,對 Chars 表執行代碼清單 24 中的 SELECT 語句(查詢條件是 chr 列大於 '2')會得到什么樣的結果呢?
代碼清單 24 選取出大於 '2' 的數據的 SELECT 語句
SELECT chr
FROM Chars
WHERE chr > '2';
大家是不是覺得應該選取出比 2 大的 3、10、11 和 222 這 4 條記錄呢?下面就讓我們來看看該 SELECT 語句的執行結果吧。
執行結果
chr
-----
3
222
沒想到吧?是不是覺得 10 和 11 比 2 大,所以也應該選取出來呢?大家之所以這樣想,是因為混淆了數字和字符串,也就是說 2 和 '2' 並不一樣。
現在,chr 列被定為字符串類型,並且在對字符串類型的數據進行大小比較時,使用的是和數字比較不同的規則。典型的規則就是按照字典順序進行比較,也就是像姓名那樣,按照條目在字典中出現的順序來進行排序。該規則最重要的一點就是,以相同字符開頭的單詞比不同字符開頭的單詞更相近。
Chars 表 chr 列中的數據按照字典順序進行排序的結果如下所示。
1
10
11
2
222
3
'10' 和 '11' 同樣都是以 '1' 開頭的字符串,首先判定為比 '2' 小。這就像在字典中“提問”“提議”和“問題”按照如下順序排列一樣。
提問
提議
問題
或者我們以書籍的章節為例也可以。1-1 節包含在第 1 章當中,所以肯定比第 2 章更靠前。
1
1-1
1-2
1-3
2
2-1
2-2
3
進行大小比較時,得到的結果是 '1-3' 比 '2' 小('1-3' < '2'),'3' 大於 '2-2'('3' > '2')。
比較字符串類型大小的規則今后還會經常使用,所以請大家牢記 [3]。
法則 8
字符串類型的數據原則上按照字典順序進行排序,不能與數字的大小順序混淆。
五、不能對 NULL 使用比較運算符
關於比較運算符還有一點十分重要,那就是作為查詢條件的列中含有 NULL 的情況。例如,我們把進貨單價(purchase_price)作為查詢條件。請注意,商品“叉子”和“圓珠筆”的進貨單價是 NULL。
我們先來選取進貨單價為 2800 日元(purchase_price = 2800)的記錄(代碼清單 25)。
代碼清單 25 選取進貨單價為 2800 日元的記錄
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price = 2800;
執行結果
product_name | purchase_price
---------------+---------------
運動T恤 | 2800
菜刀 | 2800
大家對這個結果應該都沒有疑問吧?接下來我們再嘗試選取出進貨單價不是 2800 日元(purchase_price <> 2800)的記錄(代碼清單 26)。
代碼清單 26 選取出進貨單價不是 2800 日元的記錄
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price <> 2800;
執行結果
product_name | purchase_price
---------------+---------------
T恤衫 | 500
打孔器 | 320
高壓鍋 | 5000
擦菜板 | 790
執行結果中並沒有“叉子”和“圓珠筆”。這兩條記錄由於進貨單價不明(NULL),因此無法判定是不是 2800 日元。
那如果想選取進貨單價為 NULL 的記錄的話,條件表達式該怎么寫呢?歷經一番苦思冥想后,用“purchase_price = NULL”試了試,還是一條記錄也取不出來。
代碼清單 27 錯誤的 SELECT 語句(一條記錄也取不出來)
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price = NULL;
執行結果

即使使用 <> 運算符也還是無法選取出 NULL 的記錄 [4]。因此,SQL 提供了專門用來判斷是否為 NULL 的 IS NULL 運算符。想要選取 NULL 的記錄時,可以像代碼清單 28 那樣來書寫條件表達式。
KEYWORD
IS NULL運算符
代碼清單 28 選取 NULL 的記錄
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price IS NULL;
執行結果
product_name | purchase_price
---------------+---------------
叉子 |
圓珠筆 |
反之,希望選取不是 NULL 的記錄時,需要使用 IS NOT NULL 運算符(代碼清單 29)。
KEYWORD
IS NOT NULL運算符
代碼清單 29 選取不為 NULL 的記錄
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price IS NOT NULL;
執行結果
product_name | purchase_price
---------------+---------------
T恤衫 | 500
打孔器 | 320
運動T恤 | 2800
菜刀 | 2800
高壓鍋 | 5000
擦菜板 | 790
法則 9
希望選取
NULL記錄時,需要在條件表達式中使用IS NULL運算符。希望選取不是NULL的記錄時,需要在條件表達式中使用IS NOT NULL運算符。
除此之外,對 NULL 使用比較運算符的方法還有很多,詳細內容將會在 各種各樣的函數 中進行介紹。
請參閱
(完)
