SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr] ...
[into_option]
[FROM table_references
[PARTITION partition_list]]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
[HAVING where_condition]
[WINDOW window_name AS (window_spec)
[, window_name AS (window_spec)] ...]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[into_option]
[FOR {UPDATE | SHARE}
[OF tbl_name [, tbl_name] ...]
[NOWAIT | SKIP LOCKED]
| LOCK IN SHARE MODE]
[into_option]
into_option: {
INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name] ...
}
SELECT
用於檢索從一個或多個資料表選取的資料列,並且可以包含 UNION
運算和子查詢。INTERSECT
和 EXCEPT
運算也受支援。UNION
、INTERSECT
和 EXCEPT
運算子將在本節稍後詳細說明。另請參閱第 15.2.15 節「子查詢」。
SELECT
陳述式可以從 WITH
子句開始,以定義可在 SELECT
內存取的通用資料表運算式。請參閱第 15.2.20 節「WITH (通用資料表運算式)」。
SELECT
陳述式最常用的子句如下:
每個
select_expr
指示您要檢索的資料行。必須至少有一個select_expr
。table_references
指示要從中檢索資料列的資料表或多個資料表。其語法在第 15.2.13.2 節「JOIN 子句」中描述。SELECT
支援使用PARTITION
子句明確選取分割區,其中在table_reference
中的資料表名稱後方接上分割區或子分割區 (或兩者) 的清單 (請參閱第 15.2.13.2 節「JOIN 子句」)。在此情況下,只會從清單中的分割區選取資料列,並且會忽略資料表的任何其他分割區。如需更多資訊和範例,請參閱第 26.5 節「分割區選取」。如果提供
WHERE
子句,則指示資料列必須滿足的條件,才能被選取。where_condition
是一個運算式,對於要選取的每個資料列,其值會評估為 true。如果沒有WHERE
子句,則陳述式會選取所有資料列。在
WHERE
運算式中,您可以使用 MySQL 支援的任何函式和運算子,但彙總 (群組) 函式除外。請參閱第 11.5 節「運算式」和第 14 章「函式和運算子」。
SELECT
也可用於檢索在未參照任何資料表的情況下計算的資料列。
例如:
mysql> SELECT 1 + 1;
-> 2
在未參照任何資料表的情況下,您可以在情況中指定 DUAL
作為虛擬的資料表名稱。
mysql> SELECT 1 + 1 FROM DUAL;
-> 2
DUAL
純粹是為了方便那些要求所有 SELECT
陳述式都應該有 FROM
和其他子句的人們。MySQL 可能會忽略這些子句。如果沒有參照任何資料表,MySQL 不需要 FROM DUAL
。
一般來說,使用的子句必須完全按照語法描述中顯示的順序給定。例如,HAVING
子句必須在任何 GROUP BY
子句之後且在任何 ORDER BY
子句之前。如果存在 INTO
子句,則可以出現在語法描述指示的任何位置,但在給定的陳述式中只能出現一次,不能出現在多個位置。如需有關 INTO
的更多資訊,請參閱第 15.2.13.1 節「SELECT ... INTO 陳述式」。
select_expr
詞彙清單包含選取清單,指示要檢索哪些資料行。詞彙指定資料行或運算式,或者可以使用 *
簡寫。
僅由單一未限定的
*
組成的選取清單可用作簡寫,以選取所有資料表中的所有資料行。SELECT * FROM t1 INNER JOIN t2 ...
可用作限定的簡寫,以選取指定資料表中的所有資料行。tbl_name
.*SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
如果資料表有隱藏的資料行,則
*
和
不會包含它們。若要包含,必須明確參照隱藏的資料行。tbl_name
.*在選取清單中使用未限定的
*
與其他項目可能會產生剖析錯誤。例如:SELECT id, * FROM t1
若要避免此問題,請使用限定的
參照。tbl_name
.*SELECT id, t1.* FROM t1
針對選取清單中的每個資料表使用限定的
參照。tbl_name
.*SELECT AVG(score), t1.* FROM t1 ...
以下清單提供有關其他 SELECT
子句的其他資訊:
可以使用
AS
為alias_name
select_expr
提供別名。別名會用作運算式的資料行名稱,並可用於GROUP BY
、ORDER BY
或HAVING
子句。例如:SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name;
當使用識別符號為
select_expr
設定別名時,AS
關鍵字是選用的。先前的範例可以這樣寫:SELECT CONCAT(last_name,', ',first_name) full_name FROM mytable ORDER BY full_name;
但是,由於
AS
是選用的,如果您忘記兩個select_expr
運算式之間的逗號,則可能會發生細微的問題:MySQL 會將第二個運算式解譯為別名名稱。例如,在下列陳述式中,columnb
會被視為別名名稱。SELECT columna columnb FROM mytable;
因此,建議養成習慣,在指定資料行別名時明確使用
AS
。由於在執行
WHERE
子句時可能尚未判斷資料行值,因此在WHERE
子句中參照資料行別名是不可行的。請參閱第 B.3.4.4 節「資料行別名問題」。FROM
子句指示要從中檢索資料列的資料表或多個資料表。如果您命名多個資料表,則會執行聯結。如需有關聯結語法的資訊,請參閱第 15.2.13.2 節「JOIN 子句」。對於指定的每個資料表,您可以選擇性地指定別名。table_references
tbl_name [[AS] alias] [index_hint]
使用索引提示會向最佳化工具提供有關如何在查詢處理期間選擇索引的資訊。如需有關指定這些提示的語法描述,請參閱第 10.9.4 節「索引提示」。
您可以使用
SET max_seeks_for_key=
作為強制 MySQL 偏好金鑰掃描而非資料表掃描的替代方法。請參閱第 7.1.8 節「伺服器系統變數」。value
您可以將預設資料庫中的資料表參照為
tbl_name
,或將資料庫明確地指定為db_name
.tbl_name
。您可以將資料行參照為col_name
、tbl_name
.col_name
或db_name
.tbl_name
.col_name
。除非參照不明確,否則您不需要為資料行參照指定tbl_name
或db_name
.tbl_name
前置詞。如需需要更明確資料行參照形式的模糊範例,請參閱第 11.2.2 節「識別符號限定詞」。可以使用
或tbl_name
ASalias_name
tbl_name alias_name
為資料表參照設定別名。這些陳述式是等效的:SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 WHERE t1.name = t2.name; SELECT t1.name, t2.salary FROM employee t1, info t2 WHERE t1.name = t2.name;
可以在
ORDER BY
和GROUP BY
子句中使用資料行名稱、資料行別名或資料行位置來參照選取以供輸出的資料行。資料行位置是整數,並從 1 開始。SELECT college, region, seed FROM tournament ORDER BY region, seed; SELECT college, region AS r, seed AS s FROM tournament ORDER BY r, s; SELECT college, region, seed FROM tournament ORDER BY 2, 3;
若要以相反的順序排序,請將
DESC
(遞減) 關鍵字新增至您正在排序的ORDER BY
子句中的資料行名稱。預設值為遞增順序;可以使用ASC
關鍵字明確指定。如果
ORDER BY
出現在加上括號的查詢運算式中,並且也應用於外部查詢中,則結果是未定義的,並且可能會在 MySQL 的未來版本中變更。不建議使用資料行位置,因為此語法已從 SQL 標準中移除。
當您使用
ORDER BY
或GROUP BY
對SELECT
中的資料行進行排序時,伺服器只會使用max_sort_length
系統變數指示的初始位元組數來排序值。MySQL 擴展了
GROUP BY
的用法,允許選取未在GROUP BY
子句中提及的欄位。如果您從查詢中得到的結果不如預期,請閱讀第 14.19 節「彙總函式」中關於GROUP BY
的描述。如同
WHERE
子句,HAVING
子句會指定選取條件。WHERE
子句指定選取清單中欄位的條件,但無法參照彙總函式。HAVING
子句則指定群組的條件,通常由GROUP BY
子句形成。查詢結果只會包含符合HAVING
條件的群組。(如果沒有GROUP BY
,則所有資料列會隱含地形成單一群組。)HAVING
子句幾乎是最後才套用,在項目傳送到用戶端之前,而且沒有最佳化。(LIMIT
是在HAVING
之後才套用。)SQL 標準要求
HAVING
只能參照GROUP BY
子句中的欄位或用於彙總函式中的欄位。然而,MySQL 支援此行為的擴展,允許HAVING
參照SELECT
清單中的欄位以及外部子查詢中的欄位。如果
HAVING
子句參照的欄位不明確,則會發生警告。在下列陳述式中,col2
不明確,因為它同時用作別名和欄位名稱SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;
標準 SQL 行為具有優先權,因此,如果
HAVING
欄位名稱同時在GROUP BY
中使用,也用作選取欄位清單中的別名欄位,則優先選用GROUP BY
欄位中的欄位。不要對應該放在
WHERE
子句中的項目使用HAVING
。例如,不要寫成如下所示SELECT col_name FROM tbl_name HAVING col_name > 0;
請改寫成這樣
SELECT col_name FROM tbl_name WHERE col_name > 0;
HAVING
子句可以參照彙總函式,而WHERE
子句則不能SELECT user, MAX(salary) FROM users GROUP BY user HAVING MAX(salary) > 10;
(這在某些舊版的 MySQL 中無法運作。)
MySQL 允許重複的欄位名稱。也就是說,可以有多個名稱相同的
select_expr
。這是對標準 SQL 的擴展。由於 MySQL 也允許GROUP BY
和HAVING
參照select_expr
的值,因此這可能會導致不明確的情況SELECT 12 AS a, a FROM t GROUP BY a;
在該陳述式中,兩個欄位的名稱都是
a
。為了確保將正確的欄位用於分組,請為每個select_expr
使用不同的名稱。如果存在
WINDOW
子句,則它會定義可由視窗函式參照的已命名視窗。如需詳細資訊,請參閱第 14.20.4 節「已命名視窗」。MySQL 會解析
ORDER BY
子句中未限定的欄位或別名參照,先在select_expr
值中搜尋,然後在FROM
子句的表格欄位中搜尋。對於GROUP BY
或HAVING
子句,它會在select_expr
值中搜尋之前,先搜尋FROM
子句。(對於GROUP BY
和HAVING
,這與 MySQL 5.0 之前的行為不同,後者使用的規則與ORDER BY
相同。)LIMIT
子句可用來限制SELECT
陳述式傳回的資料列數。LIMIT
接受一個或兩個數值引數,它們都必須是非負整數常數,但以下情況除外在預備陳述式中,可以使用
?
預留位置標記指定LIMIT
參數。在預存程式中,可以使用整數值常式參數或本機變數指定
LIMIT
參數。
使用兩個引數時,第一個引數會指定要傳回的第一個資料列的偏移量,而第二個引數會指定要傳回的最大資料列數。初始資料列的偏移量為 0(而非 1)
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
若要從某個偏移量擷取所有資料列到結果集的結尾,您可以使用較大的數字作為第二個參數。此陳述式會擷取從第 96 個資料列到最後一個資料列的所有資料列
SELECT * FROM tbl LIMIT 95,18446744073709551615;
使用一個引數時,該值會指定要從結果集開頭傳回的資料列數
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
換句話說,
LIMIT
等效於row_count
LIMIT 0,
。row_count
對於預備陳述式,您可以使用預留位置。下列陳述式會從
tbl
表格傳回一個資料列SET @a=1; PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?'; EXECUTE STMT USING @a;
下列陳述式會從
tbl
表格傳回第二個到第六個資料列SET @skip=1; SET @numrows=5; PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?, ?'; EXECUTE STMT USING @skip, @numrows;
為了與 PostgreSQL 相容,MySQL 也支援
LIMIT
語法。row_count
OFFSEToffset
如果
LIMIT
出現在括號中的查詢運算式中,並且也套用於外部查詢,則結果會未定義,且可能會在未來版本的 MySQL 中變更。SELECT ... INTO
形式的SELECT
可讓查詢結果寫入檔案或儲存在變數中。如需詳細資訊,請參閱第 15.2.13.1 節「SELECT ... INTO 陳述式」。如果您搭配使用
FOR UPDATE
與使用頁面或資料列鎖定的儲存引擎,則查詢檢查的資料列會寫入鎖定,直到目前交易結束。您無法在
CREATE TABLE
等陳述式中使用new_table
SELECT ... FROMold_table
...FOR UPDATE
作為SELECT
的一部分。(如果您嘗試這樣做,該陳述式會遭到拒絕,並顯示錯誤 Can't update table 'old_table
' while 'new_table
' is being created。)FOR SHARE
和LOCK IN SHARE MODE
設定共用鎖定,允許其他交易讀取檢查過的資料列,但不允許更新或刪除它們。FOR SHARE
和LOCK IN SHARE MODE
是等效的。然而,FOR SHARE
與FOR UPDATE
一樣,支援NOWAIT
、SKIP LOCKED
和OF
選項。tbl_name
FOR SHARE
是LOCK IN SHARE MODE
的替代方案,但LOCK IN SHARE MODE
仍可供回溯相容性使用。NOWAIT
會導致FOR UPDATE
或FOR SHARE
查詢立即執行,如果由於另一個交易持有的鎖定而無法取得資料列鎖定,則會傳回錯誤。SKIP LOCKED
會導致FOR UPDATE
或FOR SHARE
查詢立即執行,並從結果集中排除另一個交易鎖定的資料列。NOWAIT
和SKIP LOCKED
選項對於以陳述式為基礎的複寫是不安全的。注意略過鎖定資料列的查詢會傳回不一致的資料檢視。
SKIP LOCKED
因此不適合一般交易工作。但是,當多個工作階段存取相同的佇列式表格時,可以使用它來避免鎖定爭用。OF
會將tbl_name
FOR UPDATE
和FOR SHARE
查詢套用於已命名的表格。例如SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;
省略
OF
時,會鎖定查詢區塊參照的所有表格。因此,將鎖定子句與另一個鎖定子句組合使用而不使用tbl_name
OF
會傳回錯誤。在多個鎖定子句中指定相同的表格會傳回錯誤。如果別名在tbl_name
SELECT
陳述式中指定為表格名稱,則鎖定子句只能使用別名。如果SELECT
陳述式未明確指定別名,則鎖定子句只能指定實際的表格名稱。如需有關
FOR UPDATE
和FOR SHARE
的詳細資訊,請參閱第 17.7.2.4 節「鎖定讀取」。如需有關NOWAIT
和SKIP LOCKED
選項的更多資訊,請參閱使用 NOWAIT 和 SKIP LOCKED 的鎖定讀取並行。
在 SELECT
關鍵字之後,您可以使用許多會影響陳述式操作的修飾詞。HIGH_PRIORITY
、STRAIGHT_JOIN
以及開頭為 SQL_
的修飾詞都是 MySQL 對標準 SQL 的擴展。
ALL
和DISTINCT
修飾詞會指定是否應該傳回重複的資料列。ALL
(預設值)會指定應該傳回所有符合的資料列,包括重複的資料列。DISTINCT
會指定從結果集中移除重複的資料列。同時指定這兩個修飾詞是錯誤的。DISTINCTROW
是DISTINCT
的同義詞。DISTINCT
可以與也使用WITH ROLLUP
的查詢一起使用。HIGH_PRIORITY
賦予SELECT
比更新表格的語句更高的優先權。您應該僅針對非常快速且必須立即完成的查詢使用此選項。當表格被鎖定以進行讀取時,發出的SELECT HIGH_PRIORITY
查詢即使有更新語句正在等待表格釋放也會執行。這僅影響使用表格級別鎖定的儲存引擎(例如MyISAM
、MEMORY
和MERGE
)。STRAIGHT_JOIN
強制最佳化工具按照它們在FROM
子句中列出的順序連接表格。如果最佳化工具以非最佳順序連接表格,您可以使用此選項來加速查詢。STRAIGHT_JOIN
也可以在table_references
清單中使用。請參閱 第 15.2.13.2 節,「JOIN 子句」。STRAIGHT_JOIN
不適用於任何被最佳化工具視為const
或system
表格的表格。此類表格會產生單一資料列,在查詢執行的最佳化階段讀取,並且在查詢執行繼續之前,對其欄位的引用會被替換為適當的欄位值。這些表格會顯示在EXPLAIN
顯示的查詢計畫中最前面。請參閱 第 10.8.1 節,「使用 EXPLAIN 最佳化查詢」。此例外情況可能不適用於在外部聯結的 NULL 補全側(即LEFT JOIN
的右側表格或RIGHT JOIN
的左側表格)使用的const
或system
表格。SQL_BIG_RESULT
或SQL_SMALL_RESULT
可以與GROUP BY
或DISTINCT
一起使用,以告知最佳化工具結果集具有多個資料列或很小。對於SQL_BIG_RESULT
,MySQL 如果建立磁碟型臨時表格,則會直接使用,並且優先選擇排序,而不是使用在GROUP BY
元素上具有索引的臨時表格。對於SQL_SMALL_RESULT
,MySQL 會使用記憶體內的臨時表格來儲存結果表格,而不是使用排序。這通常不需要。SQL_BUFFER_RESULT
強制將結果放入臨時表格中。這有助於 MySQL 提早釋放表格鎖定,並且在將結果集傳送到客戶端需要很長時間的情況下有所幫助。此修飾符只能用於頂層SELECT
語句,而不能用於子查詢或後續的UNION
。SQL_CALC_FOUND_ROWS
告知 MySQL 計算結果集中會有多少資料列,而不考慮任何LIMIT
子句。然後可以使用SELECT FOUND_ROWS()
擷取資料列的數量。請參閱 第 14.15 節,「資訊函數」。注意SQL_CALC_FOUND_ROWS
查詢修飾符和隨附的FOUND_ROWS()
函數已棄用;預計會在未來版本的 MySQL 中移除。請參閱FOUND_ROWS()
的說明,以取得替代策略的資訊。在 MySQL 8.4 之前,
SQL_CACHE
和SQL_NO_CACHE
修飾符與查詢快取一起使用。查詢快取已在 MySQL 8.4 中移除。SQL_CACHE
修飾符也已移除。SQL_NO_CACHE
已棄用,且無效;預計會在未來版本的 MySQL 中移除。