我到現在還記得,第一次寫 SQL 查詢卻得到零筆結果的那個下午。
那時我檢查了資料表名稱、確認了欄位名稱、把查詢語法看了三遍。一切看起來都對,但資料庫就是不給我結果。我坐在電腦前盯著螢幕,心裡開始懷疑:是不是資料庫壞了?還是我連接有問題?
結果問題出在哪?我寫了 WHERE manager_id = NULL,而正確的寫法應該是 WHERE manager_id IS NULL。
就差一個字,我多花了一個小時 debug。
如果你正在學 SQL,遇到類似的困擾,這篇文章就是為你而寫的。因為說實話,你犯的錯誤並不是獨一無二的——每個 SQL 新手都會犯一樣的錯。包括我,包括你們公司那個資深工程師(雖然他們不會承認)。
這篇文章,我會帶你看 7 個最常見的 SQL 錯誤、為什麼會犯這些錯,以及最重要的——要怎麼修正。學會這些,你就能少花好幾個小時 debug,把時間拿去做更有意義的事。
準備好了嗎?我們開始吧。
錯誤 1:用 = NULL 而不是 IS NULL
就從害我浪費一小時的錯誤開始講起。
當你想找出資料遺失或未定義的列,直覺上會這樣寫:
SELECT * FROM employees
WHERE manager_id = NULL;
看起來很合理對吧?這段語法不會報錯,但它永遠不會回傳任何結果——就算資料表裡確實有 NULL 值也一樣。
為什麼?
因為在 SQL 的世界裡,NULL 不是「沒有東西」,而是代表**「未知」**。你無法比較兩個未知的東西。就像問「這個神秘箱子等於那個神秘箱子嗎?」答案不是對或錯,而是「我不知道」。
正確的寫法:
SELECT * FROM employees
WHERE manager_id IS NULL;
用 IS NULL 來檢查空值,用 IS NOT NULL 來找有值的資料:
SELECT * FROM employees
WHERE email IS NOT NULL;
更怪的是:NULL = NULL 的結果是 NULL(不是 TRUE)。在 SQL 裡,連兩個未知值都不相等。很玄吧?
錯誤 2:忘記在字串外加引號
這個錯誤很常見,因為一旦有人指出來,你會覺得「啊我怎麼會犯這種錯」。
你可能會這樣寫:
SELECT * FROM products
WHERE category = Electronics;
按下執行,然後——錯誤訊息跳出來。資料庫以為 Electronics 是一個欄位名稱,而不是文字內容「Electronics」。
永遠要用單引號包住文字:
SELECT * FROM products
WHERE category = 'Electronics';
數字不用加引號:
WHERE price > 100 -- 正確(數字)
WHERE status = 'active' -- 正確(文字)
小陷阱:不要用雙引號包文字。在標準 SQL 裡,雙引號是用來標示識別符(資料表或欄位名稱),不是用來包文字的。單引號 = 文字內容,這是鐵則。
錯誤 3:混用 AND 和 OR 卻不加括號
這個錯誤很微妙,因為你的查詢會跑,但結果可能不是你要的。
假設你想找出所有「電子產品」和「電腦」類別中,價格低於 500 元的商品:
SELECT * FROM products
WHERE category = 'Electronics'
OR category = 'Computers'
AND price < 500;
看起來很清楚對吧?找出兩個類別,但只要 500 元以下的。
錯!
因為 AND 的優先順序比 OR 高,SQL 會這樣理解:
「給我所有電子產品(任何價格)或是 500 元以下的電腦」
結果你會看到 2000 元的 MacBook 也跑出來,明明你不想要。
解法:用括號明確表達意圖
SELECT * FROM products
WHERE (category = 'Electronics' OR category = 'Computers')
AND price < 500;
現在 SQL 知道了:先篩選這兩個類別,然後對所有結果套用價格條件。
我的原則:只要混用 AND 和 OR,我一定加括號。每一次。就算我很確定優先順序也一樣。這能避免 bug,也讓半年後的自己看懂當初在想什麼。
錯誤 4:到處使用 SELECT *
我懂,當你在探索一張新資料表時,打 SELECT * 又快又方便:
SELECT * FROM customers;
但這裡有個重點,我希望有人早點告訴我:不要讓這個習慣進到正式程式碼裡。
為什麼?三個理由:
- **效能殺手:**你撈了一堆用不到的欄位,浪費記憶體和網路頻寬
- **未來會爆炸:**下個月有人新增一個欄位,你的程式突然收到意料外的資料
- **意圖不明:**半年後你(或同事)看到這段程式,根本不知道到底哪些欄位重要
明確指定欄位:
SELECT customer_id, first_name, email
FROM customers;
這樣更快、更安全,而且一看就知道需要什麼資料。
SELECT * 只用在:快速探索資料、測試查詢。絕對不要用在應用程式裡。未來的你會感謝現在的你。
錯誤 5:用 LIMIT 卻不加 ORDER BY
你想看幾筆範例資料:
SELECT * FROM orders
LIMIT 10;
執行,得到 10 筆。看起來沒問題。
再執行一次。得到......不一樣的 10 筆?
沒有 ORDER BY 的話,資料庫會用最方便的順序回傳資料——也就是隨機的。小資料表可能看起來固定,但在真正的生產環境資料表(幾千幾萬筆),每次執行都可能得到不同結果。
這讓 debug 變得不可能,也會讓你的應用程式行為不一致。
永遠搭配 ORDER BY 使用:
SELECT * FROM orders
ORDER BY order_date DESC
LIMIT 10;
現在你穩定地拿到最新的 10 筆訂單。可預測、可 debug、可靠。
如果你不在乎順序,那你可能根本不需要 LIMIT——你只是在探索資料而已。但如果你在應用程式裡用 LIMIT,你一定在乎拿到哪些資料,所以一定要指定 ORDER BY。
錯誤 6:在計算中忽略 NULL
這個錯誤很狡猾,因為它有時候能用......直到它不能用。
你計算折扣後的價格:
SELECT
product_name,
price,
discount,
price - discount AS sale_price
FROM products;
有折扣的商品都很好。但一旦遇到 discount 是 NULL 的商品,整個計算結果就變成 NULL。
因為:100 - NULL = NULL
不是 100。是 NULL。
任何涉及 NULL 的算術運算都會產生 NULL。NULL 會「感染」整個計算。
解法:用 COALESCE() 提供預設值
SELECT
product_name,
price,
discount,
price - COALESCE(discount, 0) AS sale_price
FROM products;
COALESCE(discount, 0) 的意思是:「如果 discount 有值就用它,如果是 NULL 就用 0 代替。」
這個技巧超實用:
total_sales / COALESCE(order_count, 1)— 避免除以零COALESCE(middle_name, '')— 把 NULL 轉成空字串COALESCE(bonus, 0)— 把沒有獎金視為零
錯誤 7:在 WHERE 中使用欄位別名
這個一開始會讓所有人困惑,因為看起來應該要能用:
SELECT
product_name,
price * 1.1 AS price_with_tax
FROM products
WHERE price_with_tax > 100;
錯誤:「欄位 'price_with_tax' 不存在。」
可是......它明明就在那裡啊!你剛剛才定義的!
問題在於:SQL 處理子句的順序是固定的。WHERE 在 SELECT 之前執行,所以資料庫處理 WHERE 時,你的別名還不存在。
你必須重複計算:
SELECT
product_name,
price * 1.1 AS price_with_tax
FROM products
WHERE price * 1.1 > 100;
有點煩,但這就是 SQL 的運作方式。
好消息:在 ORDER BY 中可以用別名,因為它在 SELECT 之後執行:
SELECT
salary * 12 AS annual_salary
FROM employees
ORDER BY annual_salary DESC; -- 這個可以!
練習題
在關掉這篇文章前,試著修正這段查詢——它包含了今天提到的 3 個錯誤:
SELECT * FROM employees
WHERE department = Sales
OR salary > 50000
AND manager_id = NULL
LIMIT 5;
找到問題了嗎?(答案在下面)
.
.
.
答案:
- 缺少引號:應該是
'Sales' - 缺少括號:應該是
(department = 'Sales' OR salary > 50000) - NULL 檢查錯誤:應該是
IS NULL - 加分題:LIMIT 前應該加
ORDER BY
你答對幾個?
寫在最後
SQL 是一個強大的工具,但就像所有工具一樣,需要時間和實踐才能精通。這些錯誤不是你的錯——它們是每個學習者必經的路。
重點是:認識它們、理解為什麼會犯這些錯,然後建立更好的習慣。
如果這篇文章幫你省下了 debug 的時間,或是讓你「啊哈!原來是這樣」,歡迎分享給其他正在學 SQL 的朋友。大家一起進步。
有任何 SQL 相關的問題或心得,也歡迎在底下留言討論。我們一起學習!
關於作者:
我是 Leon(亮之),一個熱愛分享技術知識的工程師。這個系列文章記錄了我學習 SQL 的歷程,希望能幫助更多人少走彎路。如果喜歡這篇文章,歡迎追蹤我的方格子,我會持續分享更多實用的程式技巧!














