文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
資訊 (Gzip) - 4.0Mb
資訊 (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  SELECT 陳述式

15.2.13 SELECT 陳述式

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 運算和子查詢。INTERSECTEXCEPT 運算也受支援。UNIONINTERSECTEXCEPT 運算子將在本節稍後詳細說明。另請參閱第 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 BYORDER BYHAVING 子句。例如:

    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 table_references 子句指示要從中檢索資料列的資料表或多個資料表。如果您命名多個資料表,則會執行聯結。如需有關聯結語法的資訊,請參閱第 15.2.13.2 節「JOIN 子句」。對於指定的每個資料表,您可以選擇性地指定別名。

    tbl_name [[AS] alias] [index_hint]

    使用索引提示會向最佳化工具提供有關如何在查詢處理期間選擇索引的資訊。如需有關指定這些提示的語法描述,請參閱第 10.9.4 節「索引提示」

    您可以使用 SET max_seeks_for_key=value 作為強制 MySQL 偏好金鑰掃描而非資料表掃描的替代方法。請參閱第 7.1.8 節「伺服器系統變數」

  • 您可以將預設資料庫中的資料表參照為 tbl_name,或將資料庫明確地指定為 db_name.tbl_name。您可以將資料行參照為 col_nametbl_name.col_namedb_name.tbl_name.col_name。除非參照不明確,否則您不需要為資料行參照指定 tbl_namedb_name.tbl_name 前置詞。如需需要更明確資料行參照形式的模糊範例,請參閱第 11.2.2 節「識別符號限定詞」

  • 可以使用 tbl_name AS alias_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 BYGROUP 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 BYGROUP BYSELECT 中的資料行進行排序時,伺服器只會使用 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 BYHAVING 參照 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 BYHAVING 子句,它會在 select_expr 值中搜尋之前,先搜尋 FROM 子句。(對於 GROUP BYHAVING,這與 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 OFFSET offset 語法。

    如果 LIMIT 出現在括號中的查詢運算式中,並且也套用於外部查詢,則結果會未定義,且可能會在未來版本的 MySQL 中變更。

  • SELECT ... INTO 形式的SELECT 可讓查詢結果寫入檔案或儲存在變數中。如需詳細資訊,請參閱第 15.2.13.1 節「SELECT ... INTO 陳述式」

  • 如果您搭配使用 FOR UPDATE 與使用頁面或資料列鎖定的儲存引擎,則查詢檢查的資料列會寫入鎖定,直到目前交易結束。

    您無法在CREATE TABLE new_table SELECT ... FROM old_table ... 等陳述式中使用 FOR UPDATE 作為SELECT 的一部分。(如果您嘗試這樣做,該陳述式會遭到拒絕,並顯示錯誤 Can't update table 'old_table' while 'new_table' is being created。)

    FOR SHARELOCK IN SHARE MODE 設定共用鎖定,允許其他交易讀取檢查過的資料列,但不允許更新或刪除它們。FOR SHARELOCK IN SHARE MODE 是等效的。然而,FOR SHAREFOR UPDATE 一樣,支援 NOWAITSKIP LOCKEDOF tbl_name 選項。FOR SHARELOCK IN SHARE MODE 的替代方案,但 LOCK IN SHARE MODE 仍可供回溯相容性使用。

    NOWAIT 會導致 FOR UPDATEFOR SHARE 查詢立即執行,如果由於另一個交易持有的鎖定而無法取得資料列鎖定,則會傳回錯誤。

    SKIP LOCKED 會導致 FOR UPDATEFOR SHARE 查詢立即執行,並從結果集中排除另一個交易鎖定的資料列。

    NOWAITSKIP LOCKED 選項對於以陳述式為基礎的複寫是不安全的。

    注意

    略過鎖定資料列的查詢會傳回不一致的資料檢視。SKIP LOCKED 因此不適合一般交易工作。但是,當多個工作階段存取相同的佇列式表格時,可以使用它來避免鎖定爭用。

    OF tbl_name 會將 FOR UPDATEFOR SHARE 查詢套用於已命名的表格。例如

    SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;

    省略 OF tbl_name 時,會鎖定查詢區塊參照的所有表格。因此,將鎖定子句與另一個鎖定子句組合使用而不使用 OF tbl_name 會傳回錯誤。在多個鎖定子句中指定相同的表格會傳回錯誤。如果別名在 SELECT 陳述式中指定為表格名稱,則鎖定子句只能使用別名。如果 SELECT 陳述式未明確指定別名,則鎖定子句只能指定實際的表格名稱。

    如需有關 FOR UPDATEFOR SHARE 的詳細資訊,請參閱第 17.7.2.4 節「鎖定讀取」。如需有關 NOWAITSKIP LOCKED 選項的更多資訊,請參閱使用 NOWAIT 和 SKIP LOCKED 的鎖定讀取並行

SELECT 關鍵字之後,您可以使用許多會影響陳述式操作的修飾詞。HIGH_PRIORITYSTRAIGHT_JOIN 以及開頭為 SQL_ 的修飾詞都是 MySQL 對標準 SQL 的擴展。

  • ALLDISTINCT 修飾詞會指定是否應該傳回重複的資料列。ALL (預設值)會指定應該傳回所有符合的資料列,包括重複的資料列。DISTINCT 會指定從結果集中移除重複的資料列。同時指定這兩個修飾詞是錯誤的。DISTINCTROWDISTINCT 的同義詞。

    DISTINCT 可以與也使用 WITH ROLLUP 的查詢一起使用。

  • HIGH_PRIORITY 賦予 SELECT 比更新表格的語句更高的優先權。您應該僅針對非常快速且必須立即完成的查詢使用此選項。當表格被鎖定以進行讀取時,發出的 SELECT HIGH_PRIORITY 查詢即使有更新語句正在等待表格釋放也會執行。這僅影響使用表格級別鎖定的儲存引擎(例如 MyISAMMEMORYMERGE)。

    HIGH_PRIORITY 不能與屬於 UNION 一部分的 SELECT 語句一起使用。

  • STRAIGHT_JOIN 強制最佳化工具按照它們在 FROM 子句中列出的順序連接表格。如果最佳化工具以非最佳順序連接表格,您可以使用此選項來加速查詢。 STRAIGHT_JOIN 也可以在 table_references 清單中使用。請參閱 第 15.2.13.2 節,「JOIN 子句」

    STRAIGHT_JOIN 不適用於任何被最佳化工具視為 constsystem 表格的表格。此類表格會產生單一資料列,在查詢執行的最佳化階段讀取,並且在查詢執行繼續之前,對其欄位的引用會被替換為適當的欄位值。這些表格會顯示在 EXPLAIN 顯示的查詢計畫中最前面。請參閱 第 10.8.1 節,「使用 EXPLAIN 最佳化查詢」。此例外情況可能不適用於在外部聯結的 NULL 補全側(即 LEFT JOIN 的右側表格或 RIGHT JOIN 的左側表格)使用的 constsystem 表格。

  • SQL_BIG_RESULTSQL_SMALL_RESULT 可以與 GROUP BYDISTINCT 一起使用,以告知最佳化工具結果集具有多個資料列或很小。對於 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_CACHESQL_NO_CACHE 修飾符與查詢快取一起使用。查詢快取已在 MySQL 8.4 中移除。SQL_CACHE 修飾符也已移除。SQL_NO_CACHE 已棄用,且無效;預計會在未來版本的 MySQL 中移除。