【问题标题】:Are SELECT type queries the only type that can be nested?SELECT 类型查询是唯一可以嵌套的类型吗?
【发布时间】:2014-05-10 01:33:18
【问题描述】:

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

类似(在选择中插入)

A single query:

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

【问题讨论】:

  • 在 Postgres 中,是的,使用 CTE。在 MySQL 中,没有。

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


【解决方案1】:

基本答案

CTEs (Common Table Expressions) in Postgres(就像在除 MySQL 之外的任何主要现代 RDBMS 中一样)。从包含 data-modifying CTEs 的 9.1 版开始。这些可以“嵌套”。
更新:MySQL 8.0 finally adds CTEs.

子查询不同的是,CTE 构成了优化障碍。查询规划器不能将琐碎的命令内联到主命令中或重新排序主查询和 CTE 之间的连接。子查询也是如此。对性能可能(非常)好或(非常)坏,这取决于。
无论哪种方式,CTE 都需要比子查询更多的开销(性能成本)。
更新:Postgres 12 终于可以在主查询中inline plain CTEs

您没有要求的详细信息

你的问题很基础,上面的回答大概就够了。但我会为高级用户添加一些内容(以及显示语法的代码示例)。

查询的所有 CTE 都基于数据库的相同快照。下一个 CTE 可以重用以前 CTE(内部临时表)的输出,但对其他 CTE 的基础表的影响是不可见的。多个 CTE 的序列是任意的除非通过 INSERTUPDATEDELETERETURNING 子句返回某些内容 - 与 SELECT 无关,因为它不会改变任何内容并且只是从快照中读取。

这可能会对影响同一行的多个更新产生微妙的影响。只有 一个 更新可以影响每一行。哪个受 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 中的冲突命令。

【讨论】:

  • 那个相互冲突的 CTE 示例让我有点不知所措;我会听取你的建议,并避免任何开始类似的事情!
  • @IMSoP:我花了一些时间来理解它,尽管我自己构建了它。 :)
  • 另外,请注意,虽然 CTE 术语共享相同的快照,但它们不会自动执行。例如,在 CTE 术语中的 INSERT 和面对并发事务的外部 UPDATE 之间的唯一索引上仍然完全有可能存在竞争条件。因此,可写 CTE 并没有为 upsert 问题或其他常见并发问题提供神奇的解决方案。
猜你喜欢
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
  • 2015-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-26
  • 1970-01-01
相关资源
最近更新 更多