MySQL AND 和 OR 聯合使用帶來的坑

MySQL 基礎篇

三範式

MySQL 軍規

MySQL 配置

MySQL 用戶管理和權限設置

MySQL 常用函數介紹

MySQL 字段類型介紹

MySQL 多列排序

MySQL 行轉列 列轉行

MySQL NULL 使用帶來的坑

MySQL AND 和 OR 聯合使用帶來的坑

MySQL 觸發器的使用

 

數據準備:

CREATE TABLE products
(
  prod_id    CHAR(10)      NOT NULL ,
  vend_id    CHAR(10)      NOT NULL ,
  prod_name  CHAR(255)     NOT NULL ,
  prod_price DECIMAL(8,2)  NOT NULL ,
  prod_desc  VARCHAR(1000) NULL
);
 
INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BR01', 'BRS01', '8 inch teddy bear', 5.99, '8 inch teddy bear, comes with cap and jacket');
INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BR02', 'BRS01', '12 inch teddy bear', 8.99, '12 inch teddy bear, comes with cap and jacket');
INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BR03', 'BRS01', '18 inch teddy bear', 11.99, '18 inch teddy bear, comes with cap and jacket');
INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BNBG01', 'DLL01', 'Fish bean bag toy', 3.49, 'Fish bean bag toy, complete with bean bag worms with which to feed it');
INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BNBG02', 'DLL01', 'Bird bean bag toy', 3.49, 'Bird bean bag toy, eggs are not included');
INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BNBG03', 'DLL01', 'Rabbit bean bag toy', 3.49, 'Rabbit bean bag toy, comes with bean bag carrots');
INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('RGAN01', 'DLL01', 'Raggedy Ann', 4.99, '18 inch Raggedy Ann doll');
INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('RYL01', 'FNG01', 'King doll', 9.49, '12 inch king doll with royal garments and crown');
INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('RYL02', 'FNG01', 'Queen doll', 9.49, '12 inch queen doll with royal garments and crown');

查詢數據表中的內容:

SELECT * FROM products;

 

組合 AND 和 OR 帶來了一個有趣的問題。爲了說明這個問題,來看一個例子。假如需要列出價格爲10美元(含)以上且由 BRS01 或 DLL01 製造的所有產品。下面的 SELECT 語句使用 AND 和 OR 操作符的組合建立了一個WHERE 子句:

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

 

請看上面的結果。返回的行中有兩行價格小於10美元,顯然,返回的行未按預期的進行過濾。爲什麼會這樣呢?

原因在於計算的次序。SQL(像多數語言一樣)在處理 OR 操作符前,優先處理 AND 操作符。當 SQL 看到上述 WHERE 子句時,它理解爲由供應商 DLL01 製造的任何價格爲10美元(含)以上的產品,或者由供應商 BRS01 製造的任何產品,而不管其價格如何。換句話說,由於 AND 在計算次序中優先級更高,操作符被錯誤地組合了。

此問題的解決方法是使用圓括號明確地分組相應的操作符。請看下面的 SELECT 語句及輸出:

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

這條 SELECT 語句與前一條的唯一差別是,這條語句中,前兩個條件用圓括號括了起來。因爲圓括號具有較 AND 或 OR 操作符高的計算次序,DBMS 首先過濾圓括號內的 OR 條件。這時,SQL 語句變成了選擇由供應商 BRS01 或 DLL01 製造的且價格都在10美元(含)以上的任何產品,這正是我們所希望的。

任何時候使用具有 AND 和 OR 操作符的 WHERE 子句,都應該使用圓括號明確地分組操作符。不要過分依賴默認計算次序,即使它確實是你想要的東西也是如此。使用圓括號沒有什麼壞處,它能消除歧義。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章