7.8.2. Data-Modifying Statements in WITH

7.8.2. Data-Modifying Statements in WITH
7.8.2.WITH中的数据修改语句
You can use data-modifying statements ( INSERT , UPDATE , or DELETE ) in WITH . This allows you  to perform several different operations in the same query. An example is:
可以在with中使用数据修改语句(INSERT,UPDATE或DELETE)。这样就可以在一个查询中执行多种不同的操作。例如:
 
WITH moved_rows AS (
DELETE FROM products
WHERE
"date" >= '2010-10-01' AND
"date" < '2010-11-01'
RETURNING *
)
INSERT INTO products_log
SELECT * FROM moved_rows;
 
This query effectively moves rows from products to products_log . The DELETE in WITH  deletes the specified rows from products , returning their contents by means of its RETURNING  clause; and then the primary query reads that output and inserts it into products_log .
此查询将products表中的行移动到products_log表中。WITH中的DELETE删掉products中指定的行,然后通过RETURNING子句返回删除的内容;然后主查询读取该输出并将其插入到products_log表中。
 
A fine point of the above example is that the WITH clause is attached to the INSERT , not the sub- SELECT within the INSERT . This is necessary because data-modifying statements are only allowed  in WITH clauses that are attached to the top-level statement. However, normal WITH visibility rules  apply, so it is possible to refer to the WITH statement's output from the sub- SELECT .
上面示例的一个优点是,WITH子句附加到INSERT,而不是INSERT中的SELECT子句。这是必需的,因为数据修改语句只允许附加在等层的WITH子句中。但是,通常会使用WITH可见性规则,因此可以从SELECT子句中引用WITH语句的输出。
 
Data-modifying statements in WITH usually have RETURNING clauses (see Section 6.4), as shown  in the example above. It is the output of the RETURNING clause, not the target table of the data-modifying  statement, that forms the temporary table that can be referred to by the rest of the query. If a  data-modifying statement in WITH lacks a RETURNING clause, then it forms no temporary table and  cannot be referred to in the rest of the query. Such a statement will be executed nonetheless. A notparticularly- useful example is:
如上例所示,WITH中的数据修改语句通常具有RETURNING子句(请参见6.4节)。查询中引用的是REUTRNING子句的返回值,而不是数据定义语句的目标表。如果WITH中的数据修改语句缺少RETURNING子句,则它不形成临时表,并且在查询中不能被引用。尽管如此,仍将执行该语句。 一个不是特别有用的示例:
 
WITH t AS (
DELETE FROM foo
)
DELETE FROM bar;
 
This example would remove all rows from tables foo and bar . The number of affected rows reported  to the client would only include rows removed from bar .
上例会删掉foo和bar表中的所有行。而客户端看到的被影响的行仅仅来自于bar表。
 
Recursive self-references in data-modifying statements are not allowed. In some cases it is possible  to work around this limitation by referring to the output of a recursive WITH , for example:
数据修改语句中不能使用递归自调用。一些情况下,往往可以通过在外部调用with递归来折中解决此问题。例如:
 
WITH RECURSIVE included_parts(sub_part, part) AS (
SELECT sub_part, part FROM parts WHERE part = 'our_product'
UNION ALL
SELECT p.sub_part, p.part
FROM included_parts pr, parts p
WHERE p.part = pr.sub_part
)
DELETE FROM parts
WHERE part IN (SELECT part FROM included_parts);
 
This query would remove all direct and indirect subparts of a product.
此查询会删掉一个产品中所有直接或间接的部分。
 
Data-modifying statements in WITH are executed exactly once, and always to completion, independently  of whether the primary query reads all (or indeed any) of their output. Notice that this is different  from the rule for SELECT in WITH : as stated in the previous section, execution of a SELECT is  carried only as far as the primary query demands its output.
WITH中的数据修改语句仅执行一次,并且始终执行至完成,而与主查询是否读取其输出的全部(或确实读取)无关。请注意,这与WITH中的SELECT规则不同:如上一节所述,仅在主查询需要其输出时,才执行SELECT。
 
The sub-statements in WITH are executed concurrently with each other and with the main query. Therefore, when using data-modifying statements in WITH , the order in which the specified updates  actually happen is unpredictable. All the statements are executed with the same snapshot (see Chapter  13), so they cannot “see” one another's effects on the target tables. This alleviates the effects of the  unpredictability of the actual order of row updates, and means that RETURNING data is the only way  to communicate changes between different WITH sub-statements and the main query. An example of  this is that in
WITH中的子语句彼此之间以及与主查询同时执行。因此,在WITH中使用数据修改语句时,指定更新实际发生的顺序是不可预测的。所有语句都使用相同的快照执行(请参见第13章),因此它们无法“看到”彼此对目标表的影响。这减轻了行更新实际顺序的不可预测性的影响,并且意味着RETURNING数据是在不同的WITH子语句与主查询之间传递变化的唯一途径。 例如:
 
WITH t AS (
UPDATE products SET price = price * 1.05
RETURNING *
)
SELECT * FROM products;
 
the outer SELECT would return the original prices before the action of the UPDATE , while in 
外面的SELECT语句会返回在UPDATE之前的原始价格,而在:
 
WITH t AS (
UPDATE products SET price = price * 1.05
RETURNING *
)
SELECT * FROM t;
 
the outer SELECT would return the updated data.
外面的SELECT语句会返回更新后的价格。
 
Trying to update the same row twice in a single statement is not supported. Only one of the modifications  takes place, but it is not easy (and sometimes not possible) to reliably predict which one. This also  applies to deleting a row that was already updated in the same statement: only the update is performed.  Therefore you should generally avoid trying to modify a single row twice in a single statement. In  particular avoid writing WITH sub-statements that could affect the same rows changed by the main  statement or a sibling sub-statement. The effects of such a statement will not be predictable.
不支持在单个语句中尝试两次更新同一行。只有其中一个修改会成功,但无法准确预测是哪一个更改(有时甚至是不可能)。这也适用于在 同一条语句中 删除已更新的同一行:仅执行更新。因此,通常应避免在单个语句中尝试两次修改相同行。特别要避免编写WITH子语句及主语句会影响同一行的语句。这种语句的影响是不可预测的。
 
At present, any table used as the target of a data-modifying statement in WITH must not have a conditional  rule, nor an ALSO rule, nor an INSTEAD rule that expands to multiple statements.
当前,任何在WITH中用作数据修改语句目标的表都不得具有条件规、ALSO规则、扩展为多个语句的INSTEAD规则。
发布了341 篇原创文章 · 获赞 54 · 访问量 88万+

猜你喜欢

转载自blog.csdn.net/ghostliming/article/details/104560074