文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  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 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 BYHAVING 參照 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 BYHAVING 子句,它會先搜尋 FROM 子句,然後再搜尋 select_expr 值。(對於 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 並搭配使用頁面或列鎖定的儲存引擎,則查詢所檢查的列將會寫入鎖定,直到目前交易結束為止。

    您不能在陳述式中使用 FOR UPDATE 作為 SELECT 的一部分,例如 CREATE TABLE new_table SELECT ... FROM old_table ...。(如果您嘗試這麼做,則會拒絕此陳述式並出現錯誤 在建立 'new_table' 時,無法更新表格 'old_table'。)

    FOR SHARELOCK IN SHARE MODE 會設定共用鎖定,允許其他交易讀取所檢查的列,但不允許更新或刪除它們。 FOR SHARELOCK IN SHARE MODE 是等效的。但是,如同 FOR UPDATEFOR SHARE 支援 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 不能與屬於 UNIONSELECT 陳述式一起使用。

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

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

  • 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 9.0 之前,SQL_CACHESQL_NO_CACHE 修飾符與查詢快取一起使用。查詢快取已在 MySQL 9.0 中移除。SQL_CACHE 修飾符也一併移除。SQL_NO_CACHE 已過時,並且沒有任何作用;預計在未來的 MySQL 版本中將會移除。