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_nameselect_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_referencestbl_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_nameASalias_nametbl_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_countLIMIT 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_countOFFSEToffset如果
LIMIT出現在括號中的查詢運算式中,並且也套用於外部查詢,則結果會未定義,且可能會在未來版本的 MySQL 中變更。SELECT ... INTO形式的SELECT可讓查詢結果寫入檔案或儲存在變數中。如需詳細資訊,請參閱第 15.2.13.1 節「SELECT ... INTO 陳述式」。如果您搭配使用
FOR UPDATE與使用頁面或資料列鎖定的儲存引擎,則查詢檢查的資料列會寫入鎖定,直到目前交易結束。您無法在
CREATE TABLE等陳述式中使用new_tableSELECT ... 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_nameFOR 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_nameFOR UPDATE和FOR SHARE查詢套用於已命名的表格。例如SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;省略
OF時,會鎖定查詢區塊參照的所有表格。因此,將鎖定子句與另一個鎖定子句組合使用而不使用tbl_nameOF會傳回錯誤。在多個鎖定子句中指定相同的表格會傳回錯誤。如果別名在tbl_nameSELECT陳述式中指定為表格名稱,則鎖定子句只能使用別名。如果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 中移除。