MySQL的SQL語句 - 數據操做語句(13)- 子查詢(13)

子查詢的限制html

● 一般,不能在子查詢中修改表並從同一表中進行選擇。例如,此限制適用於如下形式的語法:mysql

1. DELETE FROM t WHERE ... (SELECT ... FROM t ...);
2. UPDATE t ... WHERE col = (SELECT ... FROM t ...);
3. {INSERT|REPLACE} INTO t (SELECT ... FROM t ...);

例外狀況:若是使用的是派生表,而且派生表是物化的,而不是合併到外部查詢中,則上述禁止不適用。例子:sql

1. UPDATE t ... WHERE col = (SELECT * FROM (SELECT ...  FROM t...) AS dt ...);

在這裏,來自派生表的結果被物化爲臨時表,所以在對 t 進行更新時,t 中的相關行已經被選中。ide

一般,能夠經過添加 NO_MERGE 優化器提示來影響優化器物化派生表。函數

● 僅部分支持行比較操做:優化

■ 對於 expr [NOT] IN subquery,expr 能夠是 n 元組(使用行構造函數語法指定),子查詢能夠返回 n 元組的行。所以,容許的語法更明確地表示爲 row_constructor [NOT] IN table_subqueryrest

■ 對於 expr op {ALL|ANY|SOME} subquery,expr 必須是標量值,子查詢必須是列子查詢;它不能返回多個列行。code

換句話說,對於返回多行 n 元組的子查詢,支持如下操做:htm

1. (expr_1, ..., expr_n) [NOT] IN table_subquery

但不支持如下查詢:get

1. (expr_1, ..., expr_n) op {ALL|ANY|SOME} subquery

支持 IN 的行比較而不支持其餘形式行比較的緣由是,IN 是經過將其重寫爲一序列 = 比較和 AND 操做來實現的。這種方法不適用於 ALL、ANY 或 SOME。

● 在 MySQL 8.0.14 以前,FROM 子句中的子查詢不能是關聯子查詢。在查詢執行期間,它們被總體物化(計算以生成結果集),所以不能按外部查詢的每行計算它們。優化器延遲物化直到須要結果,這可能容許避免物化。

● 對於某些子查詢運算符,MySQL 在 子查詢 中不支持使用 LIMIT:

1. mysql> SELECT * FROM t1
2.        WHERE s1 IN (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1);
3. ERROR 1235 (42000): This version of MySQL doesn't yet support
4.  'LIMIT & IN/ALL/ANY/SOME subquery'

● MySQL 容許子查詢引用存儲函數,該函數具備修改數據的反作用,例如向表中插入行。例如,若是 f() 插入行,則如下查詢能夠修改數據:

1. SELECT ... WHERE x IN (SELECT f() ...);

此行爲是 SQL 標準的擴展。在 MySQL 中,它能夠產生不肯定的結果,由於對於給定查詢的不一樣的執行,f() 可能會執行不一樣的次數,這取決於優化器選擇如何處理它。

對於基於語句或混合格式的複製,這種不肯定性的一個含義是,這樣的查詢可能在源及其從屬庫上生成不一樣的結果。

官方網址:
https://dev.mysql.com/doc/refman/8.0/en/subquery-restrictions.html

相關文章
相關標籤/搜索