我尝试更新在同一查询中使用WITH
子句创建的记录,如下所示:
WITH
document AS (
INSERT INTO documents (name) VALUES ($1)
RETURNING *
)
UPDATE documents
SET documents.description = $2
FROM document
WHERE documents.id = document.id;
我也试过
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;
但它似乎不起作用。我知道这个例子很傻,因为我可以同时创建一个同时包含名称和描述的新文档,但我需要它在我的应用程序中这样做;这个例子是故意简化的。
我创建了一个带有真实世界示例的Gist。我知道我可以将更新document_id
的逻辑嵌入到函数体中。我猜。但是假设urls
不仅可以对应于文档,还可以对应于许多其他实体,例如文档,故事,用户,文章,标签等等,将对所有这些实体的引用嵌入到函数体中是繁琐,因为(由于函数重载)我将不得不创建像get_url_for_document(id uuid)
,get_url_for_story(id uuid)
,get_url_for_user(id uuid)
等函数。
答案 0 :(得分:2)
在两个单独的语句中或在函数内部执行。由于实施WITH的方式,你不能像你尝试的那样去做。
WITH中的子语句彼此同时执行 并与主要查询。因此,在使用数据修改时 WITH中的语句,实际指定更新的顺序 发生是不可预测的。所有语句都以相同的方式执行 快照(见第13章),所以他们不能"看"彼此的影响 在目标表上。
答案 1 :(得分:1)
你想要做的事是不可能的。
来自手册:https://www.postgresql.org/docs/current/static/queries-with.html
WITH t AS (
UPDATE products SET price = price * 1.05
RETURNING *
)
SELECT * FROM products;
外部SELECT将在UPDATE操作之前返回原始价格,而在
中WITH t AS (
UPDATE products SET price = price * 1.05
RETURNING *
)
SELECT * FROM t;
外部SELECT将返回更新的数据。
在您给出的示例中,您的更新尝试对不存在的行执行操作。使用WITH子句无法修复此问题。
我很想知道为什么你的代码强迫你这样做。