1. 程式人生 > >Mysql 8.0 第13章 SQL語句的語法 (第2節)

Mysql 8.0 第13章 SQL語句的語法 (第2節)

文章目錄

內容太多,按小節開。上一節見 第 13.1節
翻譯居多,譯者附加了自己的例子,感覺的翻譯不準的地方,已經附加了原文!

13.2 資料操作語句(DML)

13.2.1 CALL語法

CALL sp_name(
[parameter[,...]]) CALL sp_name[()]

CALL語句呼叫先前使用CREATE PROCEDURE定義的儲存過程。

不帶引數的儲存過程有兩種呼叫方式CALL p()或者CALL p(他們是等價的)。

CALL可以使用 OUT或 INOUT引數。當過程返回時,客戶端程式還可以獲取在例程中執行的最終語句受影響的行數:在SQL級別,呼叫 ROW_COUNT()函式; 從C API方面,可以呼叫 mysql_affected_rows()函式。

有關未處理條件對過程引數的影響的資訊,請參見 第13.6.7.8節“條件處理和OUT或INOUT引數”

要使用OUT或 INOUT引數從過程中獲取值 ,請通過使用者變數傳遞引數,然後在過程返回後檢查變數的值。(如果要呼叫從另一個儲存過程或函式內的程式,也可以通過常規引數或區域性例程變數作為IN或INOUT 引數)。對於一個INOUT引數,它傳遞給過程之前初始化它的值。以下過程具有OUT引數,此過程在INOUT引數上設定當前伺服器版本的 ,還有一個遞增的值:

CREATE PROCEDURE p (OUT ver_param VARCHAR(25), INOUT incr_param INT)
BEGIN
  # Set value of OUT parameter
  SELECT VERSION() INTO ver_param;
  # Increment value of INOUT parameter
  SET incr_param = incr_param + 1;
END;

在呼叫過程之前,初始化要作為INOUT引數傳遞的變數。呼叫該過程後,將設定或修改兩個變數的值:

mysql> SET @increment
= 10; mysql> CALL p(@version, @increment); mysql> SELECT @version, @increment; +--------------------+------------+ | @version | @increment | +--------------------+------------+ | 8.0.3-rc-debug-log | 11 | +--------------------+------------+

在使用了PREPARE和 EXECUTE的CALL預準備語句中,佔位符可用於IN,OUT和 INOUT引數。這些型別的引數可以使用如下:

mysql> SET @increment = 10;
mysql> PREPARE s FROM 'CALL p(?, ?)';
mysql> EXECUTE s USING @version, @increment;
mysql> SELECT @version, @increment;
+--------------------+------------+
| @version           | @increment |
+--------------------+------------+
| 8.0.3-rc-debug-log |         11 |
+--------------------+------------+

要編寫使用CALLSQL語句執行生成結果集的儲存過程的C程式, 必須啟用CLIENT_MULTI_RESULTS。這是因為每個CALL返回結果以指示呼叫狀態,以及可能由過程中執行的語句返回的任何結果集。如果CALL用於執行包含預準備語句的任何儲存過程,必須啟用CLIENT_MULTI_RESULTS。無論何時載入這樣的過程都無法確定這些語句是否會產生結果集,因此有必要假設它們會產生結果集。

呼叫mysql_real_connect()時會預設啟用CLIENT_MULTI_RESULTS,可以通過傳遞CLIENT_MULTI_RESULTS 標誌本身顯式啟用,也可以通過啟用CLIENT_MULTI_STATEMENTS(它會隱式啟用 CLIENT_MULTI_RESULTS)。

要處理mysql_query()mysql_real_query()執行的CALL 語句的結果,請使用迴圈mysql_next_result()來確定是否有更多結果。有關示例,請參見 第28.7.19節“C API多語句執行支援”

C程式可以使用prepared-statement介面來執行 CALL語句,訪問 OUT和INOUT引數。這是通過mysql_stmt_next_result()迴圈處理CALL語句的結果來完成的。有關示例,請參見 第28.7.21節“C API準備的CALL語句支援”。提供MySQL介面的語言可以使用預準備 CALL語句直接檢索OUT和INOUT 過程引數。

檢測到儲存程式引用的物件的元資料更改,並在下次執行程式時自動重新分析受影響的語句。有關更多資訊,請參見 第8.10.3節“準備語句和儲存程式的快取”

13.2.2 DELETE語法

DELETE是一個從表中刪除行的DML語句。

一個DELETE語句可以用WITH子句開始,用來定義DELETE內可以訪問的公共表示式 。請參見第13.2.13節“WITH語法(公用表表達式)”

13.2.2.1 單表語法

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]

DELETE語句從tbl_name中刪除行並返回已刪除行的數量。要檢查已刪除行的數量,請呼叫 第12.15節“資訊函式”中所述的ROW_COUNT()。

主要部分
WHERE子句中的引數標識要刪除的行。如果沒有WHERE子句,則刪除所有行。

where_condition是一個表示式,對於要刪除的每一行,計算結果為true。它的規定如 第13.2.10節“SELECT語法”中所述

如果指定了ORDER BY子句,則按指定的順序刪除行。 LIMIT子句限制了可以刪除的行數。這些子句適用於單表刪除,但不適用於多表刪除。

13.2.2.2 多表語法

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    tbl_name[.*] [, tbl_name[.*]] ...
    FROM table_references
    [WHERE where_condition]

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    FROM tbl_name[.*] [, tbl_name[.*]] ...
    USING table_references
    [WHERE where_condition]

13.2.2.3 相關介紹

許可權
您需要表上的DELETE許可權才能從中刪除行。您需要對只讀取的列的SELECT許可權,例如在 WHERE子句中指定的列。

效能
當您不需要知道已刪除行的數量時,TRUNCATE TABLE語句比 沒有 WHERE子句的DELETE語句更快。不同的是TRUNCATE TABLE不能在事務中使用或者如果您對錶有鎖定。請參見 第13.1.37節“TRUNCATE TABLE語法”第13.3.6節“LOCK TABLES和UNLOCK TABLES語法”

刪除操作的速度也可能受 第8.2.5.3節“優化DELETE語句”中討論的因素的影響。

為確保給定DELETE 語句不佔用太多時間,IMIT row_count子句指定要刪除的最大行數。如果要刪除的行數大於限制,請重複DELETE語句,直到受影響的行數小於LIMIT值。

子查詢
在一個子查詢中,無法對一個表既DELETE又SELECT
譯者例項:

mysql> delete from t_data where id > 5051638 and id in (select id from t_data where id> 5051637);
Error Code: 1093. You can't specify target table 't_data' for update in FROM clause

分割槽表
DELETE支援使用PARTITION選項顯式分割槽選擇,該選項獲取一個或多個分割槽或子分割槽(或兩者)的逗號分隔名稱列表,從中選擇要刪除的行。未包含在列表中的分割槽將被忽略。給定一個表t帶有一個分割槽表 p0,執行該語句DELETE FROM t PARTITION (p0)對錶的執行效果與執行ALTER TABLE t TRUNCATE PARTITION (p0)相同; 在這兩種情況下,分割槽p0中的所有行都將被刪除。

PARTITION可以與WHERE條件一起使用 ,在這種情況下,僅對列出的分割槽中的行測試條件。例如, DELETE FROM t PARTITION (p0) WHERE c < 5 僅從p0分割槽中刪除條件c < 5為true的行。

該PARTITION選項也可用於多表DELETE語句。您可以在FROM選項中指定的每個表中使用最多一個此類 選項。

有關更多資訊和示例,請參見 第23.5節“分割槽選擇”

自動增長列
如果刪除包含列的最大值AUTO_INCREMENT的行 ,則不會為MyISAM或InnoDB表重用該值。如果在autocommit模式(預設啟用)下使用DELETE FROM tbl_name刪除表中的所有行(沒有WHERE子句) ,則除了MyISAM和InnoDB之外的所有儲存引擎都會重新開始 。InnoDB 表的這種行為有一些例外,如 第15.6.1.4節“InnoDB中的AUTO_INCREMENT處理”中所述。

對於MyISAM表,您可以在多列索引中指定一個AUTO_INCREMENT二級列。在這種情況下,即使對於MyISAM 表,也會重複使用從序列頂部刪除的值。請參見第3.6.9節“使用AUTO_INCREMENT”

修飾符
DELETE語句支援以下修飾符:

如果指定LOW_PRIORITY,則伺服器會延遲執行DELETE,直到沒有其他客戶端從表中讀取。這會影響只使用表級鎖的儲存引擎(例如MyISAM,MEMORY和MERGE)。

對於MyISAM表,如果使用 QUICK修飾符,則儲存引擎在刪除期間不會合並索引葉,這可能會加速某些型別的刪除操作。

IGNORE修飾符導致MySQL刪除行的過程中忽略的錯誤。(解析階段遇到的錯誤以常規方式處理。)由於使用IGNORE,被忽略的錯誤 將作為警告返回。有關更多資訊,請參閱 IGNORE關鍵字和嚴格SQL模式的比較

刪除順序
如果DELETE語句包含 ORDER BY子句,則按照子句指定的順序刪除行。與結合LIMIT使用會很有用。例如,以下語句查詢與WHERE子句匹配的行,對其進行timestamp_column排序,並刪除第一個(最舊的):

DELETE FROM somelog WHERE user = 'jcole'
ORDER BY timestamp_column LIMIT 1;

ORDER BY 還有助於刪除所需的順序中的行,以避免參照完整性違規。

InnoDB表
如果要從大表中刪除許多行,則可能會超出InnoDB表的鎖定表大小。為了避免這個問題,或者只是為了最小化表保持鎖定的時間,以下策略(根本不使用 DELETE)可能會有所幫助:

  1. 選擇不要刪除的行到與原始表具有相同結構的空表中:
INSERT INTO t_copy SELECT * FROM t WHERE ... ;
  1. 使用RENAME TABLE以原子移動原始表的方式進行,並重新命名拷貝表為原來表的名稱:
RENAME TABLE t TO t_old, t_copy TO t;
  1. 刪除原始表:
DROP TABLE t_old;

沒有其他會話可以訪問在RENAME TABLE執行時所涉及的表 ,因此重新命名操作不受併發問題的影響。請參見 第13.1.36節“RENAME TABLE語法”

MyISAM表

多表刪除
您可以在DELETE語句中指定多個表,以 根據WHERE子句中的條件從一個或多個表中刪除行 。您不能在多表刪除中使用ORDER BY或LIMIT。table_references子句列出了連線中涉及的表,如 第13.2.10.2節“JOIN語法”中所述

對於第一個多表語法,僅刪除FROM子句前列出的表中的匹配行。對於第二個多表語法,僅刪除FROM子句(在USING子句之前)中列出的表中的匹配行。結果是您可以同時從多個表中刪除行,並具有僅用於搜尋的其他表:

DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3
WHERE t1.id=t2.id AND t2.id=t3.id;

要麼:

DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3
WHERE t1.id=t2.id AND t2.id=t3.id;

這些語句查詢刪除行的時候使用所有三個表,但只從t1和t2中刪除匹配行 。

前面的示例使用INNER JOIN,但多表DELETE語句可以使用SELECT語句中允許的其他型別的連線 ,例如LEFT JOIN。例如,要刪除t1中存在而 t2中不存在的行,請使用LEFT JOIN:

DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;

語法允許在每個 tbl_name語句之後使用.*,這是為了與Access相容 。

如果使用多表DELETE語句涉及InnoDB具有外來鍵約束的表的時候,則MySQL優化器可能會按照與其父/子關係不同的順序處理表。在這種情況下,語句失敗並回滾。相反,您應該從單個表中刪除並依賴於 InnoDB提供的ON DELETE功能,以便相應地修改其他表。

注意
如果宣告表的別名,則在引用表時必須使用別名:

DELETE t1 FROM test AS t1, test2 WHERE ...

多表DELETE中的表別名 只應在table_references語句的部分宣告。在其他地方,允許別名引用但不允許別名宣告。

正確:

DELETE a1, a2 FROM t1 AS a1 INNER JOIN t2 AS a2
WHERE a1.id=a2.id;

DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2
WHERE a1.id=a2.id;

不正確:

DELETE t1 AS a1, t2 AS a2 FROM t1 INNER JOIN t2
WHERE a1.id=a2.id;

DELETE FROM t1 AS a1, t2 AS a2 USING t1 INNER JOIN t2
WHERE a1.id=a2.id;

13.2.3 DO語法

DO expr [, expr] ...

DO執行表示式但不返回任何結果。在大多數方面,它 DO是SELECT expr, ...的簡寫,但有一個優點,當你不關心結果時它會稍微快一些。

DO主要用於具有副作用的函式,例如 RELEASE_LOCK()

示例:此SELECT語句暫停,但也會生成結果集:

mysql> SELECT SLEEP(5);
+----------+
| SLEEP(5) |
+----------+
|        0 |
+----------+
1 row in set (5.02 sec)

使用DO,暫停而不產生結果集:

mysql> DO SLEEP(5);
Query OK, 0 rows affected (4.99 sec)

這可能很有用,例如在儲存函式或觸發器中,它禁止生成結果集的語句。

DO只執行表示式。它不能用於所有SELECT可以使用的情況。例如,DO id FROM t1它是無效的,因為它引用了一個表。

13.2.10 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 ...]
    [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 OUTFILE 'file_name'
        [CHARACTER SET charset_name]
        export_options
      | INTO DUMPFILE 'file_name'
      | INTO var_name [, var_name]]
    [FOR {UPDATE | SHARE} [OF tbl_name [, tbl_name] ...] [NOWAIT | SKIP LOCKED] 
      | LOCK IN SHARE MODE]]

SELECT用於檢索從一個或多個表中選擇的行,並且可以包括 UNION語句和子查詢。請參見第13.2.10.3節“UNION語法”第13.2.11節“子查詢語法”。一個 SELECT語句可以用WITH子句開始 來定義SELECT內可以訪問的公共表的表示式 。請參見第13.2.13節“WITH語法(公用表表達式)”

最常用的SELECT 子部分是:

  • 每個select_expr都表示要一個檢索的列。必須至少有一個 select_expr。

  • table_references表示要從中檢索行的一個或多個表。其語法在 第13.2.10.2節“JOIN語法”中描述。

  • SELECT支援使用PARTITION選項進行顯式地分割槽選擇,可以是分割槽列表或子分割槽(或兩者)跟隨在table_reference(參見 第13.2.10.2節“JOIN語法”)後面。在這種情況下,僅從列出的分割槽中選擇行,並忽略表的任何其他分割槽。有關更多資訊和示例,請參見 第23.5節“分割槽選擇”

SELECT ... PARTITION從使用MyISAM儲存引擎的表中執行表級鎖(以及分割槽鎖),僅鎖定PARTITION選項指定的分割槽或子分割槽 。

有關更多資訊,請參閱 分割槽和鎖定

  • 如果給出WHERE子句,則表示行必須滿足要選擇的條件。 where_condition是一個表示式,對於要選擇的每一行,計算結果為true。如果沒有WHERE子句,該語句將選擇所有行 。

在WHERE表示式中,您可以使用MySQL支援的任何函式和運算子,但聚合(彙總)函式除外。請參見 第9.5節“表示式”第12章“ 函式和運算子”

SELECT 也可用於檢索計算的行而不引用任何表。

例如:

mysql> SELECT 1 + 1;
        -> 2

在沒有引用表的情況下, 您可以指定DUAL為虛擬表名:

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

DUAL純粹是為了方便那些要求所有SELECT 語句應該具有FROM以及可能的其他子句的人。FROM DUAL可以忽略。

通常,使用的子句必須完全按照語法描述中顯示的順序給出。例如,一個 HAVING子句必須在任何 GROUP BY子句之後和任何ORDER BY子句之前。例外情況是INTO子句可以如語法描述中所示出現,也可以緊接在select_expr列表後面出現 。有關更多資訊INTO,請參見 第13.2.10.1節“SELECT … INTO語法”

select_expr列表包括指示要檢索哪些列的選擇列表。可以指定列或表示式或可以使用*

  • *可用作選擇從所有表中所有列的簡寫:
SELECT * FROM t1 INNER JOIN t2 ...
  • tbl_name.* 從指定的表中選擇所有列:
SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
  • *和select的定義列表中的其他術語一起使用可能會產生解析錯誤。要避免此問題,請使用tbl_name.*
SELECT AVG(score), t1.* FROM t1 ...

以下列表提供了有關其他SELECT子句的其他資訊 :

  • select_expr可以使用別名,形式為AS alias_name。別名用作表示式的列名,並且可以在GROUP BY,ORDER BY,HAVING中被使用 。
    例如:
SELECT CONCAT(last_name,', ',first_name) AS full_name
  FROM mytable ORDER BY full_name;

AS可以不寫,前面的例子可以這樣編的:

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

不允許在WHERE子句中引用列別名 ,因為在WHERE 執行子句時可能尚未確定列值。請參見 第B.6.4.4節“列別名的問題”

  • FROM table_references子句指示要從中檢索行的一個或多個表。如果您為多個表命名,則表示您正在執行連線。有關連線語法的資訊,請參見第13.2.10.2節“JOIN語法”。對於指定的每個表,您可以選擇指定別名。
tbl_name [[AS] alias] [index_hint]

index_hint的使用為優化器提供了有關如何在查詢處理期間選擇索引的資訊。有關指定這些提示的語法的說明,請參見 第8.9.4節“索引提示”。

  • 另一種方法,您可以使用SET max_seeks_for_key=value 強制MySQL優先進行key掃描而不是表掃描。請參見 第5.1.8節“伺服器系統變數”

  • 您可以將預設資料庫中的表稱為 tbl_name或 db_name.tbl_name ,同樣地列名稱也可以加表和資料庫名字首。您無需為一個引用指定這些字首,除非引用不明確。有關需要更明確的列引用形式的歧義的示例,請參見第9.2.1節“識別符號限定符”

  • 表的引用可以使用別名

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子句中再次使用,使用方式可以是列名,列別名或列位置。列位置(不推薦使用列位置,因為已從SQL標準中刪除了語法)是整數,以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;

預設為升序(ASC),降序使用DESC

如果ORDER BY在子查詢中發生並且也在外部查詢中應用,則最外層 ORDER BY優先。例如,以下語句的結果按a的降序排序:

(SELECT ... ORDER BY a) ORDER BY a DESC;

在MySQL 8.0.13之前,MySQL支援非標準語法擴充套件,允許GROUP BY的列指定排序順序。MySQL 8.0.12及更高版本支援 ORDER BY中分組功能,因此不再需要使用此擴充套件。(Bug#86312,Bug#26073525)這也意味著您這樣使用:

SELECT a, b, COUNT(c) AS t FROM test_table GROUP BY a,b ORDER BY a,t DESC;

從MySQL 8.0.13開始,不允許為GROUP BY中的列指定排序順序

  • 當您使用 ORDER BY 或 GROUP BY 對SELECT中的列進行排序時,伺服器使用max_sort_length系統變數(預設1024)指示的初始位元組數對值進行排序 。

  • MySQL擴充套件了使用GROUP BY功能,以允許GROUP BY子句中可以出現SELECT部分沒出現的欄位(譯者注:如下面例子所示)。如果你沒有期望的結果,請閱讀 第12.20,“集合(GROUP BY)功能”

mysql> select cpm,cjd from t1 group by id;

以前,不允許ORDER BY在具有WITH ROLLUP修飾符的查詢中使用它。從MySQL 8.0.12開始,此限制被取消。請參見 第12.20.2節“GROUP BY Modifiers”。

  • 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行為,出現上例情況,則會優先選擇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;
  • WINDOW子句(如果存在)定義了可由視窗函式引用的命名視窗。有關詳細資訊,請參見第12.21.4節“命名Windows”

  • MySQL先搜尋select_expr中的列確定 ORDER BY子句中的列名或別名,然後再從FROM子句中搜索 。對於GROUP BY或者HAVING 子句,它先從FROM子句搜尋,再從select_expr 中搜索。(對於GROUP BY和 HAVING,這與MySQL 5.0之前使用相同ORDER BY規則的行為不同。)

  • LIMIT子句可用於約束SELECT語句返回的行數 。 LIMIT取一個或兩個數字引數,這些引數必須都是非負整數常量,但有以下例外:

  • 在預準備語句中,LIMIT 可以使用? 佔位符標記指定引數。

  • 在儲存的程式中,LIMIT 可以使用整數值例程引數或區域性變數指定引數。

第一個引數指定從第幾條開始(預設0),第二個引數指定要返回的最大行數:

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 @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;
  • SELECT ... INTO形式的SELECT 使查詢結果能夠寫入檔案或儲存在變數中。有關更多資訊,請參見 第13.2.10.1節“SELECT … INTO語法”

  • 如果儲存引擎使用頁鎖或行鎖,你使用了FOR UPDATE,則查詢檢查的行將被寫入鎖定,直到當前事務結束。

某些情況,不能將FOR UPDATE用作SELECT宣告中的 一部分,例如CREATE TABLE new_table SELECT ... FROM old_table ... 。(如果您嘗試這樣做,則該語句將被拒絕,並且錯報錯Can't update table 'old_table' while 'new_table' is being created

FOR SHARELOCK IN SHARE MODE設定共享鎖,允許其他事務讀取已檢查的行,但不允許更新或刪除它們。 FOR SHARE和LOCK IN SHARE MODE是等價的。然而FOR SHARE,像FOR UPDATE,支援 NOWAIT,SKIP LOCKED,OF tbl_name 選項。FOR SHARE是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;

在SELECT關鍵字之後,您可以使用許多影響語句操作的修飾符。HIGH_PRIORITYSTRAIGHT_