[英]Instantly update created record with a WITH clause
I'm trying to update a record, created with WITH
clause in the same query, like so: 我正在尝试更新在同一查询中使用
WITH
子句创建的记录,如下所示:
WITH
document AS (
INSERT INTO documents (name) VALUES ($1)
RETURNING *
)
UPDATE documents
SET documents.description = $2
FROM document
WHERE documents.id = document.id;
I've also tried 我也试过了
WITH
new_document AS (
INSERT INTO documents (name) VALUES ($1)
RETURNING *
),
updated_document AS (
UPDATE documents
SET documents.description = $2
WHERE documents.id = (SELECT id FROM new_document)
RETURNING *
)
SELECT * FROM updated_document;
But it doesn't seem to work. 但它似乎没有用。 I know this example is silly since I can simply create a new document with both name and description at the same time, but I need it to do it this way in my app;
我知道这个例子很傻,因为我可以同时创建一个同时包含名称和描述的新文档,但我需要它在我的应用程序中这样做; the example is simplified on purpose.
这个例子是故意简化的。
I've created a Gist with a real world example. 我用真实世界的例子创造了一个要点 。 I know I can embed the logic of updating
document_id
into the function body. 我知道我可以将更新
document_id
的逻辑嵌入到函数体中。 I guess. 我猜。 But imagine that
urls
can correspond not only to documents, but to many other entities, like, documents, stories, users, articles, tags, etc., etc., embedding references to all these entities into the function body is tedious, since (due to function overloading) I would have to create functions like get_url_for_document(id uuid)
, get_url_for_story(id uuid)
, get_url_for_user(id uuid)
, etc., etc. 但是想象一下,
urls
不仅可以对应于文档,还可以对应于许多其他实体,例如文档,故事,用户,文章,标签等等,将所有这些实体的引用嵌入到函数体中是很乏味的,因为(由于函数重载)我必须创建函数,如get_url_for_document(id uuid)
, get_url_for_story(id uuid)
, get_url_for_user(id uuid)
等等。
Do it in two separate statements or inside a function. 在两个单独的语句中或在函数内部执行。 You cannot do it like you tried due to the way how WITH is implemented.
由于实现WITH的方式,你不能像你尝试的那样去做。
From documentation : 来自文档 :
The sub-statements in WITH are executed concurrently with each other and with the main query.
WITH中的子语句彼此同时并与主查询一起执行。 Therefore, when using data-modifying statements in WITH, the order in which the specified updates actually happen is unpredictable.
因此,在WITH中使用数据修改语句时,指定更新实际发生的顺序是不可预测的。 All the statements are executed with the same snapshot (see Chapter 13), so they cannot "see" one another's effects on the target tables.
所有语句都使用相同的快照执行(参见第13章),因此它们无法“看到”彼此对目标表的影响。
What you are attempting to do is impossible. 你试图做的事是不可能的。
From the manual: https://www.postgresql.org/docs/current/static/queries-with.html 从手册: https : //www.postgresql.org/docs/current/static/queries-with.html
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将返回更新的数据。
In your given example your update trying to act on rows which don't exist. 在您给出的示例中,您的更新尝试对不存在的行执行操作。 This is not fixable using a WITH clause.
使用WITH子句无法修复此问题。
I would be interested to understand why your code has forced you to do it this way. 我很想知道为什么你的代码强迫你这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.