首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL EXISTS 子查詢 Bug:聚合函數導致誤判為 TRUE 的深度分析

     編輯:MySQL 資料庫相關知識

現象重現

同一張表、同一個 WHERE 條件,EXISTS (SELECT id ...) 回傳 0 筆,但 EXISTS (SELECT MAX(id) ...) 卻回傳全表行數——顯然被誤判為 TRUE。

官方文檔承諾 vs 現實

「MySQL ignores the SELECT list in such a subquery, so it makes no difference.」
—— MySQL 官方文檔

實測 MySQL 5.6.31 / 5.7.14 均存在此 Bug。

最小複現腳本

CREATE TABLE t3(id INT, t DATETIME);
INSERT INTO t3 VALUES(1, '20160812');

-- 正確:id=2 不存在,回傳空集
SELECT 1 FROM dual WHERE EXISTS (SELECT id FROM t3 WHERE id=2);
-- Empty set

-- 錯誤:加上 MAX() 卻回傳 1
SELECT 1 FROM dual WHERE EXISTS (SELECT MAX(id) FROM t3 WHERE id=2);
-- +---+
-- | 1 |
-- +---+

執行計劃揭示根因

查詢重寫後 SQL (SHOW WARNINGS)判斷
EXISTS (SELECT id ...)WHERE 0正確判定 FALSE
EXISTS (SELECT MAX(id) ...)WHERE 1錯誤判定 TRUE

優化器將聚合函數子查詢錯誤重寫為常數 1,導致語意改變。

官方 Bug 追蹤

已提交:Bug #82562

規避最佳實踐

  • 永遠使用 SELECT * 或 SELECT 1,避免任何聚合/函數操作
  • 測試驗證:ABS()、FLOOR() 不觸發此 Bug,但為求穩健仍建議統一用 *

版本修復狀態

MySQL 8.0.13+ 已修復(優化器重寫邏輯重構)。5.7/5.6 維護版本需自行規避。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved