MySQL 在標準 SQL 基礎上有獨特的查詢語法與限制。掌握 DUAL、LIMIT、子查詢更新限制及繞過方案,能寫出更地道、高效的 MySQL 查詢。
無需實表即可 SELECT 標量/函數結果,兼容 Oracle 習慣。
-- MSSQL: 直接 SELECT SELECT 1, 'A'; -- Oracle: 必須 FROM DUAL SELECT 1, 'A' FROM DUAL; -- MySQL: 兩種皆支援 SELECT 1, 'A'; SELECT 1, 'A' FROM DUAL;
實際執行計劃中 DUAL 為常量表,零開銷。
替代 MSSQL TOP,語法更靈活、效率更高(無需全排序)。
-- 取前 1 行(優化器可提前終止) SELECT * FROM usr LIMIT 1; -- 偏移量 + 條數:跳過 0 行,取 2 行(即第 1-2 行) SELECT * FROM usr LIMIT 0, 2; -- 等價於 LIMIT 2 OFFSET 0
-- 報錯:This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' SELECT * FROM usr WHERE u_id IN (SELECT u_id FROM usr WHERE dept='信息部' LIMIT 1);
SELECT * FROM usr
WHERE u_id IN (
SELECT * FROM (
SELECT u_id FROM usr WHERE dept='信息部' LIMIT 1
) aa
);
原理:衍生表物質化後,外層視為常規表,繞過限制。
-- 報錯:You can't specify target table 'usr' for update in FROM clause UPDATE usr SET usr_name='匿名' WHERE u_id IN (SELECT u_id FROM usr WHERE dept='信息部');
UPDATE usr SET usr_name='匿名'
WHERE u_id IN (
SELECT * FROM (
SELECT u_id FROM usr WHERE dept='信息部'
) aa
);
| 特性 | MySQL LIMIT | MSSQL TOP |
|---|---|---|
| 執行策略 | 優化器可提前終止掃描 | 通常先全排序再取前 N |
| 大數據分頁 | LIMIT 1000000,10 極慢(需掃 100 萬行) | 同樣慢 |
| 優化建議 | 游標分頁 / 覆蓋索引 / 延遲關聯 | OFFSET-FETCH / ROW_NUMBER() |
WHERE id > last_id LIMIT 20(游標式)優於 LIMIT offset, 20EXISTS / JOIN 替代 IN (SELECT...)SELECT * 可能帶來額外開銷,建議顯式列出所需列WITH),可替代衍生表寫法,可讀性更強