如下內容均翻譯自 MySQL 5.6 Reference Manual 來自一個四級都還沒過的渣渣 經過閱讀官方文檔加深對一些sql注入的理解mysql
13.2.9.1 SELECT ... INTO Syntax
13.2.9.2 JOIN Syntax
13.2.9.3 UNION Syntaxsql
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 [, select_expr ...] [FROM table_references [PARTITION partition_list] [WHERE where_condition] [GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_condition] [ORDER BY {col_name | expr | position} [ASC | DESC], ...] [LIMIT {[offset,] row_count | row_count OFFSET offset}] [PROCEDURE procedure_name(argument_list)] [INTO OUTFILE 'file_name' [CHARACTER SET charset_name] export_options | INTO DUMPFILE 'file_name' | INTO var_name [, var_name]] [FOR UPDATE | LOCK IN SHARE MODE]]
SELECT用於從一個或多個表中取回行,能夠包含UNION語句和子查詢。參見第13.2.9.3節,UNION語法,和第13.2.10節,Subquery語法。數據庫
SELECT語句最經常使用的子句是:緩存
每一個select_expr指示要檢索的列。 必須至少有一個select_expr。服務器
table_references指示要從中檢索行的一個或多個表。 其語法在第13.2.9.2節「JOIN語法」中描 述。函數
SELECT支持使用partition關鍵字進行顯式分區選擇,在table_reference中的表名後面有一個分區或子分區列表(或二者都有)(請參見第13.2.9.2節「聯接語法」)。在這種狀況下,只從列出的分區中選擇行,而忽略表中的任何其餘分區。有關更多信息和示例,請參見第19.5節「分區選擇」。優化
SELECT ... PARTITION from tables using storage engines such as MyISAM that perform table-level locks (and thus partition locks) lock only the partitions or subpartitions named by the PARTITION option.翻譯
For more information, see Section 19.6.4, 「Partitioning and Locking」.code
WHERE子句(若是給定)指示要選擇行必須知足的一個或多個條件。where_condition是一個表達式,對於要選擇的每一行,其計算結果爲true。若是沒有WHERE子句,該語句將選擇全部行。orm
在WHERE表達式中,您可使用MySQL支持的任何函數和運算符,聚合(摘要)函數除外。參見第9.5節「表達式」和第12章「函數和運算符」。
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子句能夠如語法描述中所示出現,也能夠緊跟在select_expr列表以後出現。 有關INTO的更多信息,請參見第13.2.9.1節「SELECT ... INTO語法」。
select_expr列表術語包含選擇列表,該列表指示要檢索哪些列。術語指定列或表達式,或者可使用 * 來簡寫
一個只包含一個非限定 * 的選擇列表能夠用做從全部表中選擇全部列的簡寫
SELECT * FROM t1 INNER JOIN t2 ...
tbl_name.* 可用做限定簡寫,從指定表中選擇全部列:
SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
與選擇列表中的其餘項一塊兒使用非限定可能會產生解析錯誤。爲了不這個問題,請使用限定的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.4.4.4節,列別名的問題。FROM table_references子句指示從中檢索行的一個或多個表。若是您指定了多個表,則表示您正在執行JOIN。有關JOIN語法的信息,請參見13.2.9.2節「JOIN語法」。對於指定的每一個表,您能夠選擇指定別名。
tbl_name [[AS] alias] [index_hint]
index_hint的使用爲優化器提供了關於如何在查詢處理過程當中選擇索引的信息。有關指定這些提示的語法描述,請參見第8.9.3節「索引提示」。
您可使用SET max seek for key=value做爲另外一種強制MySQL選擇鍵掃描而不是表掃描的方法。參見第5.1.7節,服務器系統變量。引用表時可使用 tbl_name AS alias_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出如今子查詢中而且也應用於外部查詢,則最外面的ORDER BY優先。例如,如下語句的結果按降序排列,而不是升序排列:
(SELECT ... ORDER BY a) ORDER BY a DESC;不建議使用列位置,由於該語法已從SQL標準中刪除。
MySQL擴展了GROUP BY子句,所以您還能夠在子句中指定的列以後指定ASC和DESC
SELECT a, COUNT(b) FROM test_table GROUP BY a DESC;
若是使用GROUP BY,輸出行將根據GROUP BY列進行排序,就好像對相同的列都有一個ORDER BY同樣。爲了不GROUP BY排序產生的開銷,請添加ORDER BY NULL
SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;不同意依賴隱式GROUP BY排序(即,在沒有ASC或DESC指示符的狀況下進行排序)。要生成給定的排序順序,請爲「GROUP BY」列使用顯式的ASC或DESC指示符,或者提供ORDER 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使用不一樣的名稱。
LIMIT子句可用於約束SELECT語句返回的行數。LIMIT接受一個或兩個數值參數,除了這些例外,它們都必須是非負整數常量
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。
對於prepared statements,可使用佔位符。下面的語句將從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出如今子查詢中而且也應用於外部查詢,則最外面的LIMIT優先。例如,如下語句產生兩行,而不是一行:
(SELECT ... LIMIT 1) LIMIT 2;
PROCEDURE子句指定應處理結果集中數據的過程。 有關示例,請參見第8.4.2.4節「使用PROCEDURE ANALYZE」,其中介紹了ANALYZE,該過程可用於獲取可能有助於減少表大小的最佳列數據類型的建議。
UNION語句中不容許使用PROCEDURE子句。
SELECT的SELECT ... INTO形式使查詢結果可以寫入文件或存儲在變量中。 有關更多信息,請參見第13.2.9.1節「SELECT ... INTO語法」。
若是對使用頁鎖或行鎖的存儲引擎使用FOR UPDATE,則查詢檢查的行將被寫入鎖定,直到當前事務結束。 使用LOCK IN SHARE MODE設置共享鎖,容許其餘事務讀取已檢查的行,但不容許更新或刪除它們。 請參見第14.7.2.4節「鎖定讀取」。
此外,您不能在諸如CREATE TABLE new_table SELECT ... FROM old_table ....之類的語句中使用FOR UPDATE做爲SELECT的一部分。(若是您嘗試這樣作,語句將被拒絕,並顯示錯誤 Can't update table 'old_table' while 'new_table' is being created.)這是MySQL 5.5及更早版本的行爲更改,它容許CREATE TABLE ... SELECT語句在正在建立的表以外的表中進行更改。
在SELECT關鍵字以後,您可使用許多影響語句操做的修飾符。 HIGH_PRIORITY(高優先級),STRAIGHT_JOIN(直鏈接)和以SQL_開頭的修飾符是標準SQL的MySQL擴展。
高優先級賦予SELECT比更新表的語句更高的優先級。您應該只將它用於很是快速且必須當即完成的查詢。即便有更新語句等待表釋放,在表被鎖定讀取時發出的SELECT HIGH_PRIORITY查詢也會運行。這僅影響僅使用表級鎖定的存儲引擎(如MyISAM、MEMORY和MERGE)。
HIGH_PRIORITY不能與屬於UNION的SELECT語句一塊兒使用。STRAIGHT _ JOIN強制優化器按照表在FROM子句中列出的順序來鏈接表。若是優化器以非最佳順序鏈接表,您可使用它來加速查詢。還能夠在table_references列表中使用STRAIGHT _ JOIN。參見第13.2.9.2節「鏈接語法」。
STRAIGHT_JOIN不適用於優化程序視爲const或system的任何表。 這樣的表生成單行,在查詢執行的優化階段讀取,而且在查詢執行進行以前用適當的列值替換對其列的引用。 這些表將首先出如今EXPLAIN顯示的查詢計劃中。 請參見第8.8.1節「使用EXPLAIN優化查詢」。 此異常可能不適用於在外鏈接的NULL補充端(即LEFT JOIN的右側表或RIGHT JOIN的左側表)上使用的const或系統表。SQL_CACHE和SQL_NO_CACHE修飾符會影響查詢緩存中查詢結果的緩存(請參見第8.10.3節「MySQL查詢緩存」)。 SQL_CACHE告訴MySQL將結果存儲在查詢緩存中(若是它是可緩存的,而且query_cache_type系統變量的值是2或DEMAND)。 使用SQL_NO_CACHE,服務器不使用查詢緩存。 它既不檢查查詢緩存,也不檢查結果是否已緩存,也不緩存查詢結果。 (因爲解析器中的限制,空格字符必須位於SQL_NO_CACHE關鍵字以前和以後;非空格(如換行符)會致使服務器檢查查詢緩存以查看結果是否已緩存。)
這兩個修飾符是互斥的,若是同時指定它們則會發生錯誤。 此外,子查詢(包括FROM子句中的子查詢)和第一個SELECT之外的聯合中的SELECT語句不容許使用這些修飾符。
對於視圖,若是SQL_NO_CACHE出如今查詢中的任何SELECT中,則適用。 對於可高速緩存的查詢,若是SQL_CACHE出如今查詢引用的視圖的第一個SELECT中,則應用SQL_CACHE。
使用存儲引擎從分區表中進行選擇,例如使用表級鎖的MyISAM,只鎖定那些包含與SELECT語句WHERE子句匹配的行的分區。(使用行級鎖定的存儲引擎(如InnoDB)不會出現這種狀況。)有關更多信息,請參見第19.6.4節「分區和鎖定」。