首頁 / CompScience / Database / MySQL / MySQL SELECT語法

MySQL SELECT語法

2013-05-09_112859

這是MySQL 5實力養成暨評量裡的3-41.『為了在產品資料表格(product)中進行查詢時,欲得到已經供貨的供應商代號(supp_no),且自動去除重複的資料錄,使每一供應商代號只顯示一次,則可執行下列哪些SQL命令?

答案:C) supp_no From product; (D) supp_no From product;

平常用慣了的DISTINCT,這回碰到DISTINCTROW就手足無措了,我們真的是識淺了。還是努力地看手冊吧,請參考

MySQL 5.7 Reference Manual :: 13 SQL Statement Syntax :: 13.2 Data Manipulation Statements :: 13.2.9 SELECT Syntax

或簡體手冊

MySQL 5.1参考手册 :: 13. SQL语句语法::13.2. 数据操作语句::13.2.7. SELECT语法

繁體轉譯如下:

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
      [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr, ...
    [INTO OUTFILE 'file_name' export_options
      | INTO DUMPFILE 'file_name']
    [FROM table_references
    [WHERE where_definition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_definition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC] , ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [FOR UPDATE | LOCK IN SHARE MODE]]

SELECT用於恢復從一個或多個資料表中選擇的行,並可以加入UNION語句和子查詢。請參見13.2.7.2節,「UNION語法
13.2.8節,「Subquery語法」

·         每個select_expr都指示一個您想要恢復的列。

·         table_references指示行從哪個資料表或哪些資料表中被恢復。在13.2.7.1節,「JOIN語法」中對該語法進行了說明。

·         where_definition包括關鍵詞WHERE,後面接一個資料表達式。該資料表達式指示被選擇的行必須滿足的條件。

有的行在計算時未引用任何資料表。SELECT也可以用於恢復這類行。

舉例說明:

> SELECT 1 + 1;
        -> 2

所有被使用的子句必須按語法說明中顯示的順序嚴格地排序。例如,一個HAVING子句必須位於GROUP BY子句之後,並位於ORDER BY子句之前。

·         使用AS alias_name可以為select_expr給定一個別名。此別名用作資料表達式的列名,可以用於GROUP BY、ORDER BY或HAVING子句。例如:

·                mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name
·                    -> FROM mytable ORDER BY full_name;

在為select_expr給定別名時,AS關鍵詞是自選的。前面的例子可以這樣編寫:

mysql> SELECT CONCAT(last_name,', ',first_name) full_name
    -> FROM mytable ORDER BY full_name;

因為AS是自選的,如果您忘記在兩個select_expr資料表達式之間加逗號,則會出現一個小問題:MySQL會把第二個資料表達式理解為一個別名。例如,在以下語句中,columnb被作為別名對待:

mysql> SELECT columna columnb FROM mytable;

因此,使用AS明確地指定列的別名,把它作為習慣,是一個良好的操作規範。

·         在一個WHERE子句中使用列別名是不允許的,因為當執行WHERE子句時,列值可能還沒有被確定。請參見A.5.4節,「與列別名有關的問題」

·         FROM table_references子句指示行從哪些資料表中被恢復。如果您命名的資料表多於一個,則您在進行一個聯合操作。要瞭解有關聯合語法的說明,請參見13.2.7.1節,「JOIN語法」。對於每一個被指定的資料表,您可以自選地指定一個別名。

·                tbl_name [[AS] alias]
·                    [{USE|IGNORE|FORCE} INDEX (key_list)]

使用USE INDEX、IGNORE INDEX、FORCE INDEX可以向最佳化符提示如何選擇索引。這部分內容在13.2.7.1節,「JOIN語法」中進行了討論。

您可以使用SET max_seeks_for_key=value作為一種替代方法,來促使MySQL優先採用關鍵字掃瞄,替代資料表掃瞄。

·         您可以把當前資料庫中的一個資料表作為tbl_name(在當前資料庫中)引用,或作為db_name.tbl_name引用,來明確地指定一個資料庫。您可以把一列作為col_nametbl_name.col_name引用或作為db_name.tbl_name.col_name引用。您不需要對一個列引用指定一個tbl_namedb_name.tbl_name前綴,除非此引用意義不明確。意義不明確時,要求指定明確的列引用格式。有關示範見9.2節,「資料庫、資料表、索引、列和別名」

·         在沒有資料表被引用的情況下,允許您指定DUAL作為一個假的資料表名。

·                mysql> SELECT 1 + 1 FROM DUAL;
·                        -> 2

有些伺服器要求一個FROM子句。DUAL僅用於與這些伺服器兼容。如果沒有資料表被引用,則MySQL不要求該子句,前面的語句可以按以下方法編寫:

mysql> SELECT 1 + 1;
        -> 2

·         使用tbl_name AS alias_nametbl_name alias_name可以為一個資料表引用起別名:

·                mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
·                    ->     WHERE t1.name = t2.name;
·                mysql> SELECT t1.name, t2.salary FROM employee t1, info t2
·                    ->     WHERE t1.name = t2.name;

·         在WHERE子句中,您可以使用MySQL支援的所有函數,不過總計(總結)函數除外。請參見第12章:函數和操作符

·         被選擇的用於輸出的列可以使用列名稱、列別名或列位置被引用到ORDER BY和GROUP BY子句中。列位置為整數,從1開始:

·                mysql> SELECT college, region, seed FROM tournament
·                    ->     ORDER BY region, seed;
·                mysql> SELECT college, region AS r, seed AS s FROM tournament
·                    ->     ORDER BY r, s;
·                mysql> SELECT college, region, seed FROM tournament
·                    ->     ORDER BY 2, 3;

要以相反的順序進行分類,應把DESC(降序)關鍵字新增到ORDER BY子句中的列名稱中。預設值為升序;該值可以使用ASC關鍵詞明確地指定。

不建議使用列位置,因為該語法已經從SQL標準中刪除。

·         如果您使用GROUP BY,則輸出行根據GROUP BY列進行分類,如同您對相同的列進行了ORDER BY。MySQL對GROUP BY進行了延伸,因此您可以在各列(在子句中進行命名)的後面指定ASC和DESC:

·                SELECT a, COUNT(b) FROM test_table GROUP BY a DESC

·         MySQL對GROUP BY的使用進行了延伸,允許選擇在GROUP BY子句中沒有被提到的字段。如果您沒有得到預期的結果,請閱讀GROUP BY的說明,請參見12.10節,「與GROUP BY子句同時使用的函數和修改程式

·         GROUP BY允許一個WITH ROLLUP修飾符。請參見12.10.2節,「GROUP BY修改程式」

·         HAVING子句基本上是最後使用,只位於被發送給客戶端的條目之前,沒有進行最佳化。(LIMIT用於HAVING之後。)

SQL標準要求HAVING必須引用GROUP BY子句中的列或用於總計函數中的列。不過,MySQL支援對此工作性質的延伸,並允許HAVING因為SELECT清單中的列和外部子查詢中的列。

如果HAVING子句引用了一個意義不明確的列,則會出現警告。在下面的語句中,col2意義不明確,因為它既作為別名使用,又作為列名使用:

mysql> SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;

標準SQL工作性質具有優先權,因此如果一個HAVING列名既被用於GROUP BY,又被用作輸出列清單中的起了別名的列,則優先權被給予GROUP BY列中的列。

·         HAVING不能用於應被用於WHERE子句的條目。例如,不能編寫如下語句:

·                mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;

而應這麼編寫:

mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;

·         HAVING子句可以引用總計函數,而WHERE子句不能引用:

·                mysql> SELECT user, MAX(salary) FROM users
·                    ->     GROUP BY user HAVING MAX(salary)>10;

(在有些較早版本的MySQL中,本語句不運行。)

·         LIMIT子句可以被用於限制被SELECT語句返回的行數。LIMIT取一個或兩個數字自變數,自變數必須是非負的整數常數(當使用已預備的語句時除外)。

使用兩個自變數時,第一個自變數指定返回的第一行的偏移量,第二個自變數指定返回的行數的最大值。初始行的偏移量為0(不是1):

mysql> SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

為了與PostgreSQL兼容,MySQL也支援LIMIT row_count OFFSET offset語法。

如果要恢復從某個偏移量到結果集合的末端之間的所有的行,您可以對第二個參數是使用比較大的數。本語句可以恢復從第96行到最後的所有行:

mysql> SELECT * FROM tbl LIMIT 95,18446744073709551615;

使用1個自變數時,該值指定從結果集合的開頭返回的行數:

mysql> SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows

換句話說,LIMIT n與LIMIT 0,n等價。

對於已預備的語句,您可以使用位置保持符。以下語句將從tb1資料表中返回一行:

mysql> SET @a=1;
mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?";
mysql> EXECUTE STMT USING @a;

以下語句將從tb1資料表中返回第二到第六行:

mysql> SET @skip=1; SET @numrows=5;
mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?, ?";
mysql> EXECUTE STMT USING @skip, @numrows;

·         SELECT…INTO OUTFILE ‘file_name‘形式的SELECT可以把被選擇的行寫入一個檔案中。該檔案被建立到伺服器主機上,因此您必須擁有FILE權限,才能使用此語法。file_name不能是一個原有的檔案。原有檔案會阻止例如「/etc/passwd」的檔案和資料庫資料表被銷毀。

SELECT…INTO OUTFILE語句的主要作用是讓您可以非常快速地把一個資料表轉儲到伺服器機器上。如果您想要在伺服器主機之外的部分客戶主機上建立結果檔案,您不能使用SELECT…INTO OUTFILE。在這種情況下,您應該在客戶主機上使用比如「mysql –e “SELECT …” > file_name」的命令,來生成檔案。

SELECT…INTO OUTFILE是LOAD DATA INFILE的補語;用於語句的exort_options部分的語法包括部分FIELDS和LINES子句,這些子句與LOAD DATA INFILE語句同時使用。請參見13.2.5節,「LOAD DATA INFILE語法」

FIELDS ESCAPED BY用於控制如何寫入特殊字元。如果FIELDS ESCAPED BY字元不是空字元,則被用於在輸出中對以下字元設前綴:

o        FIELDS ESCAPED BY字元

o        FIELDS [OPTIONALLY] ENCLOSED BY字元

o        FIELDS TERMINATED BY和LINES TERMINATED BY值的第一個字元

o        ASCII 0(在編寫時接在轉義符後面的是ASCII 『0』,而不是一個零值字節)

如果FIELDS ESCAPED BY字元是空字元,則沒有字元被轉義,並且NULL被作為NULL輸出,而不是作為\N輸出。指定一個空的轉義符不是一個好的主意。特別是當您的數據中的字段值包含剛被給予的清單中的字元時,更是如此。

其原因是您必須對所有FIELDS TERMINATED BY, ENCLOSED BY, ESCAPED BY或LINES TERMINATED BY字元進行轉義,才能可靠地讀取檔案並返回。ASCII NUL被轉義,以便更容易地使用調頁程式觀看。

生成的檔案不必符合SQL語法,所以沒有其它的字元需要被轉義。

在下面的例子中,生成一個檔案,各值用逗號隔開。這種格式可以被許多程式使用。

SELECT a,b,a+b INTO OUTFILE '/tmp/result.text'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM test_table;

·         如果您使用INTO DUMPFILE代替INTO OUTFILE,則MySQL只把一行寫入到檔案中,不對任何列或行進行終止,也不執行任何轉義處理。如果您想要把一個BLOB值儲存到檔案中,則這個語句是有用的。

·         註釋:任何由INTO OUTFILE或INTO DUMPFILE建立的檔案都可以被伺服器主機上的所有用戶編寫。原因是,MySQL伺服器不能建立這樣的檔案,即檔案的所有者不是該檔案運行時所屬的用戶(任何時候,您都不能出於此原因或出於其它原因把mysqld作為根段運行)。該檔案必須是全局可寫的,這樣您就可以操作其中的內容。

·         有的過程應在結果集合內處理數據。PROCEDURE子句用於對這些過程進行命名。要瞭解示範,請參見27.3.1節,「步驟分析」

·         儲存引擎使用頁面或行鎖。如果您對儲存引擎使用FOR UPDATE,則受到查詢檢驗的行會被進行寫鎖定,直到當前事務結束為止。使用LOCK IN SHARE MODE可以設置一個共享鎖。共享鎖可以防止其它事務更新或刪除被檢驗的行。請參見15.2.10.5節,「鎖定讀取SELECT … FOR UPDATE和SELECT … LOCK IN SHARE MODE」

在SELECT關鍵詞的後面,您可以使用許多選項。這些選項可以影響語句的運行。

ALL, DISTINCT和DISTINCTROW選項指定是否重複行應被返回。如果這些選項沒有被給定,則預設值為ALL(所有的匹配行被返回)。DISTINCT和DISTINCTROW是同義詞,用於指定結果集合中的重複行應被刪除

HIGH_PRIORITY, STRAIGHT_JOIN和以SQL_為開頭的選項是MySQL相對於標準SQL的延伸。

·         HIGH_PRIORITY給予SELECT更高的優先權,高於用於更新資料表的語句。您應該只對查詢使用HIGH_PRIORITY。查詢速度非常快,而且立刻被執行。SELECT HIGH_PRIORITY查詢在資料表被鎖定用於讀取時被發出。即使有一個新的語句正在等待資料表變為空閒,查詢也會運行。

HIGH_PRIORITY不能和SELECT語句同時使用。SELECT語句是UNION的一部分。

·         STRAIGHT_JOIN用於促使最佳化符把資料表聯合在一起,順序按照這些資料表在FROM子句中排列的順序。如果最佳化符聯合資料表時順序不佳,您可以使用STRAIGHT_JOIN來加快查詢的速度。請參見7.2.1節,「EXPLAIN語法(獲取關於SELECT的訊息)。STRAIGHT_JOIN也可以被用於table_references清單中。請參見13.2.7.1節,「JOIN語法」

·         SQL_BIG_RESULT可以與GROUP BY或DISTINCT同時使用,來告知最佳化符結果集合有很多行。在這種情況下,MySQL直接使用以磁盤為基礎的臨時資料表(如果需要的話)。在這種情況下,MySQL還會優先進行分類,不優先使用臨時資料表。臨時資料表對於GROUP BY組分帶有關鍵字。

·         SQL_BUFFER_RESULT促使結果被放入一個臨時資料表中。這可以幫助MySQL提前解開資料表鎖定,在需要花費較長時間的情況下,也可以幫助把結果集合發送到客戶端中。

·         SQL_SMALL_RESULT可以與GROUP BY或DISTINCT同時使用,來告知最佳化符結果集合是較小的。在此情況下,MySAL使用快速臨時資料表來儲存生成的資料表,而不是使用分類。在MySQL 5.1中,通常不需要這樣。

·         SQL_CALC_FOUND_ROWS告知MySQL計算有多少行應位於結果集合中,不考慮任何LIMIT子句。行的數目可以使用SELECT FOUND_ROWS()恢復。請參見12.9.3節,「訊息函數」

·         如果您正在使用一個query_cache_type值,值為2或DEMAND,則SQL_CACHE告知MySQL把查詢結果儲存在查詢緩存中。對於使用UNION的查詢或子查詢,本選項會影響查詢中的所有SELECT。請參見5.13節,「MySQL查詢高速緩衝」

·         SQL_NO_CACHE告知MySQL不要把查詢結果儲存在查詢緩存中。請參見5.13節,「MySQL查詢高速緩衝」。對於一個使用UNION或子查詢的查詢,本選項會影響查詢中的SELECT。

馬上成為工作達人的Fans

About ㄚ琪

工作達人Fun Taiwan的創辦者及總編,可以在這裡更認識他。

發表迴響

你的電子郵件位址並不會被公開。 Required fields are marked *

*

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料

Scroll To Top