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 會先在
select_expr
值中搜尋,然後在FROM
子句的表格欄位中搜尋,以此來解析ORDER BY
子句中未限定的欄位或別名參照。對於GROUP BY
或HAVING
子句,它會先搜尋FROM
子句,然後再搜尋select_expr
值。(對於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
並搭配使用頁面或列鎖定的儲存引擎,則查詢所檢查的列將會寫入鎖定,直到目前交易結束為止。您不能在陳述式中使用
FOR UPDATE
作為SELECT
的一部分,例如CREATE TABLE
。(如果您嘗試這麼做,則會拒絕此陳述式並出現錯誤 在建立 'new_table
SELECT ... FROMold_table
...new_table
' 時,無法更新表格 'old_table
'。)FOR SHARE
和LOCK IN SHARE MODE
會設定共用鎖定,允許其他交易讀取所檢查的列,但不允許更新或刪除它們。FOR SHARE
和LOCK IN SHARE MODE
是等效的。但是,如同FOR UPDATE
,FOR SHARE
支援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
)。HIGH_PRIORITY
不能與屬於UNION
的SELECT
陳述式一起使用。STRAIGHT_JOIN
強制最佳化工具依照FROM
子句中列出的順序聯結資料表。如果最佳化工具以非最佳順序聯結資料表,您可以使用此選項來加速查詢。STRAIGHT_JOIN
也可以在table_references
清單中使用。請參閱第 15.2.13.2 節「JOIN 子句」。STRAIGHT_JOIN
不適用於任何最佳化工具視為const
或system
的資料表。這類資料表會產生單一列,在查詢執行最佳化階段讀取,且在查詢執行繼續之前,其欄位的參照會被替換為適當的欄位值。這些資料表會優先顯示在EXPLAIN
所顯示的查詢計畫中。請參閱第 10.8.1 節「使用 EXPLAIN 最佳化查詢」。此例外情況可能不適用於外部聯結的 NULL 補全側使用的const
或system
資料表(即LEFT JOIN
的右側資料表或RIGHT JOIN
的左側資料表)。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 9.0 之前,
SQL_CACHE
和SQL_NO_CACHE
修飾符與查詢快取一起使用。查詢快取已在 MySQL 9.0 中移除。SQL_CACHE
修飾符也一併移除。SQL_NO_CACHE
已過時,並且沒有任何作用;預計在未來的 MySQL 版本中將會移除。