MySQL SELECT 基本語法
簡介
在資料庫的日常操作中,SELECT 是最常使用、也是最重要的語句之一。它負責從資料表中取出符合條件的資料,讓我們能夠進一步分析、呈現或處理。無論是建立報表、實作搜尋功能,或是後端 API 回傳資料,都離不開 SELECT。
本單元將從最基礎的語法說起,帶你一步步掌握查詢的核心概念,並提供實務範例、常見陷阱與最佳實踐,讓你能在開發過程中快速、正確地取出想要的資料。
核心概念
1. 基本 SELECT 結構
最簡單的 SELECT 只需要指定要查詢的欄位與來源表格:
SELECT column1, column2
FROM table_name;
- SELECT 後面列出欲返回的欄位,若要全部欄位可使用
*。 - FROM 指定資料來源的資料表。
小技巧:在開發階段,先寫
SELECT *確認欄位名稱,再逐步改為具體欄位,能減少拼寫錯誤。
2. 為什麼要使用別名 (Alias)
別名讓回傳的欄位名稱更易讀,或在多表查詢時避免衝突。
SELECT employee_id AS id,
first_name AS 名,
salary AS 月薪
FROM employees;
AS為可選的關鍵字,直接寫空格也可:employee_id id。- 別名支援 Unicode,因此可以直接使用中文欄位名。
3. 條件篩選 – WHERE
WHERE 讓我們只取出符合條件的資料,常見的比較運算子有 =、<>、>、<、BETWEEN、LIKE 等。
SELECT *
FROM orders
WHERE order_date >= '2024-01-01'
AND status = 'completed';
- 多條件使用
AND(同時滿足)或OR(任一滿足)。 - 日期字串建議使用 ISO 標準
YYYY-MM-DD,可避免時區與格式問題。
4. 排序 – ORDER BY
ORDER BY 讓結果依指定欄位排序,預設為 升冪 (ASC),欲降冪則使用 DESC。
SELECT product_name, price
FROM products
WHERE price > 1000
ORDER BY price DESC;
- 多欄位排序時,依左至右的優先順序依序比較:
ORDER BY category ASC, price DESC。
5. 限制筆數 – LIMIT (MySQL 專屬)
在大量資料時,常用 LIMIT 只取前幾筆,配合 OFFSET 可實作分頁。
-- 取第 2 頁,每頁 10 筆
SELECT *
FROM customers
ORDER BY created_at DESC
LIMIT 10 OFFSET 10;
提醒:
OFFSET效能較差,若資料筆數龐大,建議改用「鍵值分頁」或「游標」技巧。
程式碼範例
範例 1:簡單查詢所有欄位
-- 取得 employees 表的全部資料
SELECT *
FROM employees;
此查詢在開發測試階段很有用,但正式上線時建議改為指定欄位,以減少不必要的 I/O。
範例 2:欄位別名與條件篩選
SELECT employee_id AS 員工編號,
CONCAT(first_name, ' ', last_name) AS 姓名,
salary AS 月薪
FROM employees
WHERE salary BETWEEN 30000 AND 60000 -- 薪資介於 3~6 萬
AND status = 'active'; -- 僅列出在職員工
CONCAT用來合併字串,讓姓名一次呈現在同一欄位。
範例 3:排序與分頁
SELECT order_id, customer_id, total_amount, order_date
FROM orders
WHERE order_date >= '2024-01-01'
ORDER BY order_date DESC, total_amount ASC
LIMIT 20 OFFSET 40; -- 取第 3 頁 (每頁 20 筆)
結合
ORDER BY與LIMIT,即可快速完成分頁功能。
範例 4:使用聚合函式與 GROUP BY
SELECT customer_id,
COUNT(*) AS 訂單筆數,
SUM(total_amount) AS 總消費金額
FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31'
GROUP BY customer_id
HAVING SUM(total_amount) > 5000; -- 只保留消費超過 5,000 的客戶
GROUP BY必須與聚合函式(COUNT、SUM、AVG…)一起使用,HAVING用於篩選聚合結果。
範例 5:子查詢 (Nested SELECT)
SELECT e.employee_id,
e.first_name,
e.last_name,
(SELECT COUNT(*)
FROM orders o
WHERE o.employee_id = e.employee_id) AS 訂單數量
FROM employees e
WHERE e.status = 'active';
子查詢在
SELECT中直接計算每位員工的訂單筆數,避免額外的 JOIN。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方式 |
|---|---|---|
使用 SELECT * |
會把所有欄位都拉回,增加 I/O 與網路流量。 | 僅列出需要的欄位,並使用別名提升可讀性。 |
忘記加上 WHERE |
大表全表掃描可能導致瞬間鎖表、效能崩潰。 | 務必檢查條件,必要時加上索引。 |
LIKE 前綴 % |
%abc 會讓搜尋無法使用索引,變成全表掃描。 |
若可能,盡量改成 abc%,或使用全文索引 (FULLTEXT)。 |
忽略 NULL 判斷 |
= 無法比較 NULL,會得到意外結果。 |
使用 IS NULL / IS NOT NULL 或 COALESCE。 |
LIMIT 與 OFFSET 大數值 |
大量偏移會造成 MySQL 讀取大量不必要的行。 | 採用「鍵值分頁」 (WHERE id > last_id) 或使用 Cursor。 |
| 未使用交易 (TRANSACTION) | 多筆 SELECT/UPDATE 組合時,資料可能不一致。 | 需要時以 START TRANSACTION 包裹,確保原子性。 |
最佳實踐小結
- 明確指定欄位,配合別名提升可讀性。
- 適時加索引:
WHERE、JOIN、ORDER BY、GROUP BY常用欄位皆應考慮建立索引。 - 避免過度使用子查詢:在可能的情況下,改用
JOIN以提升效能。 - 使用參數化查詢(Prepared Statement)防止 SQL Injection。
- 盡量在開發環境先測試,觀察
EXPLAIN執行計畫,找出瓶頸。
實際應用場景
| 場景 | SELECT 用法 | 為何重要 |
|---|---|---|
| 商品搜尋 | SELECT id, name, price FROM products WHERE name LIKE '手機%' ORDER BY price ASC LIMIT 20; |
為前端即時搜尋提供快速、分頁結果,提升使用者體驗。 |
| 月度營收報表 | SELECT DATE_FORMAT(order_date,'%Y-%m') AS month, SUM(total_amount) AS revenue FROM orders GROUP BY month ORDER BY month; |
直接在資料庫完成彙總,減少程式端計算,報表產出更即時。 |
| 使用者登入檢查 | SELECT user_id FROM users WHERE email = ? AND password_hash = ? AND status = 'active'; |
只回傳必要的欄位,降低資料外洩風險,同時配合參數化查詢提升安全性。 |
| 後端 API 分頁 | SELECT * FROM articles ORDER BY created_at DESC LIMIT 10 OFFSET 30; |
讓 API 能依頁面返回固定筆數,減少前端一次載入過多資料。 |
| 資料遷移 | INSERT INTO archive_orders SELECT * FROM orders WHERE order_date < '2023-01-01'; |
使用 SELECT 搭配 INSERT,一次性搬移大量舊資料,簡化 ETL 流程。 |
總結
SELECT 是 MySQL 與所有關聯式資料庫的核心查詢語句,掌握它的基本語法與常用技巧,是每位開發者的必備能力。本文從 基本結構、條件篩選、排序與分頁、聚合與子查詢 四大面向說明,並提供多個實務範例、常見陷阱與最佳實踐,協助你在日常開發中寫出 高效、可讀、且安全 的查詢。未來只要持續運用 EXPLAIN 觀察執行計畫、適時調整索引與查詢寫法,你就能在面對大資料量時,仍保持查詢的快速回應,為系統穩定性與使用者體驗奠定堅實基礎。祝你在 MySQL 的世界裡查詢無礙,開發順利!