SELECT类型查询是唯一可以嵌套的类型吗?

时间:2014-03-30 20:14:51

标签: mysql sql postgresql common-table-expression nested-queries

是否可以将非选择查询(更新,插入,删除)嵌入到另一个查询中?

类似(选择中的插入)

A single query:

select such,and,such from .... where .... insert into .... ;

1 个答案:

答案 0 :(得分:5)

基本答案

CTEs (Common Table Expressions) in Postgres(与MySQL之外的任何主要现代RDBMS一样)。从版本9.1开始,包括data-modifying CTEs。那些可以“嵌套” 更新:MySQL 8.0 finally adds CTEs.

子查询不同,CTE构成优化障碍。查询计划程序无法将简单命令内联到主命令或重新排序主查询和CTE之间的连接。子查询也是如此。可能(非常)好或(非常)不利于表现,这取决于 无论哪种方式,CTE都需要比子查询更多的开销(性能成本)。

您没有要求的详细信息

你的问题很基本,上面的内容可能足以回答。但我会为高级用户添加一些内容(以及显示语法的代码示例)。

查询的所有CTE都基于数据库的相同快照。下一个CTE可以重用以前CTE的输出(内部临时表),但对其他CTE不可见对基础表的影响。多个CTE的序列是任意的,除非返回RETURNING INSERT UPDATEDELETESELECT的一些内容 - {{1}的irrelvant因为它不会改变任何东西而只是从快照中读取。

这会对影响同一行的多个更新产生微妙的影响。只有一个更新可以影响每一行。哪一个受CTE序列的影响。

尝试预测结果:

CREATE TEMP TABLE t (t_id int, txt text);
INSERT INTO t VALUES (1, 'foo'), (2, 'bar'), (3, 'baz');

WITH sel AS (SELECT * FROM t)
   , up1 AS (UPDATE t SET txt = txt || '1' WHERE t_id = 1 RETURNING *)
   , up2 AS (UPDATE t SET txt = t.txt || '2'
             FROM   up1
             WHERE  up1.t_id = t.t_id
             RETURNING t.*)
   , ins AS (INSERT INTO t VALUES (4, 'bamm'))
   , up3 AS (UPDATE t SET txt = txt || '3' RETURNING *)
SELECT 'sel' AS source, * FROM sel
UNION ALL
SELECT 'up1' AS source, * FROM up1
UNION ALL
SELECT 'up2' AS source, * FROM up2
UNION ALL
SELECT 'up3' AS source, * FROM up3
UNION ALL
SELECT 't'   AS source, * FROM t;

SQL Fiddle

不要失望,我怀疑这里有很多人可以做到。 :)
其中的要点是:避免在CTE中发生冲突的命令。