我有一张桌子 foo
Table "public.foo"
Column | Type | Modifiers
-------------------+-----------------------------+-------------------------------------
foo_id | uuid | not null default uuid_generate_v1()
col1 | uuid |
col2 | uuid |
col3 | uuid | not null
我有一个视图 goo_view ,它主要从foo中选择,但也加入了另一个表
SELECT * from foo LEFT JOIN foo_helper USING (foo_id);
我有以下CTE查询,其中我尝试插入表 foo ,同时返回相应的 goo_view 信息
WITH ins AS (
INSERT INTO foo (col1,col2, col3) VALUES (111,222,333) RETURNING foo_id
)
SELECT v.foo_id, v.col1, v.col2, v.fk1
FROM goo_view v
JOIN ins
USING (foo_id)
然而结果是空的。
如果我运行插入并单独选择它是否有效,是否存在导致此失败的时序?
是什么工作?
答案 0 :(得分:2)
为什么在CTE中使用插入?
WITH ins AS (
select 111 as col1, 222 as col2, 333 as col3
)
. . .
你的语法真的有效吗?我以前没见过。哇,我刚刚学到了一些东西。这似乎是Postgres syntax。
我最好的猜测是你正在使用的返回子句返回一个foo_id。 。 。你刚插入的那个。这个foo_id可能不存在于goo_view中,因此没有匹配和空集。
而且,您要做的是在文档中不允许明确:
WITH中的子语句彼此同时执行 并与主要查询。因此,在使用数据修改时 WITH中的语句,实际指定更新的顺序 发生是不可预测的。所有语句都以相同的方式执行 快照(见第13章),因此他们无法“看到”彼此的影响 在目标表上。这减轻了影响 行更新的实际顺序的不可预测性,并且意味着 RETURNING数据是在两者之间进行通信的唯一方式 不同的WITH子语句和主查询。 。
因此,您不会在视图中看到新行。要解决此问题,您必须使用from
返回的结果显式引用returning
子句中的CTE。
答案 1 :(得分:1)
由于视图在SQL命令启动状态下从表foo
中选择,因此您必须重写为:
WITH ins AS (
INSERT INTO foo (col1,col2, col3) VALUES (111,222,333)
RETURNING foo_id, col1, col2
)
SELECT i.foo_id, i.col1, i.col2, h.fk1
FROM ins i
LEFT JOIN foo_helper h USING (foo_id);
这样您就可以获取新插入的值并将辅助表连接到它。
答案 2 :(得分:1)
BTW:关于隔离级别,CTE,链式RETURNING,子查询或普通连接之间(应该)没有区别。如果“后续”子查询引用实际的表元组(即选择),它应该“查看”查询开始的行。
在其他情况下,下面带有自联接更新湖的查询无效:
SET search_PATH='tmp';
DROP TABLE ztable CASCADE;
CREATE TABLE ztable
( id integer NOT NULL PRIMARY KEY
, payload varchar
);
INSERT INTO ztable(id,payload) VALUES (1,'one' ), (2,'two' ), (3,'three')
,(4,'four' ), (5,'five' ), (6,'six' );
SELECT * FROM ztable;
-- This can only work if
-- t2 is seen in its original form
-- **before the update**
UPDATE ztable t1
SET payload=t2.payload
FROM ztable t2
WHERE t1.id = 7-t2.id
;
SELECT * FROM ztable;
结果:
CREATE TABLE
INSERT 0 6
id | payload
----+---------
1 | one
2 | two
3 | three
4 | four
5 | five
6 | six
(6 rows)
UPDATE 6
id | payload
----+---------
6 | one
5 | two
4 | three
3 | four
2 | five
1 | six
(6 rows)
由返回产生的CTE返回的元组或“链表表达式”当然是虚拟的;它们并不是指实际的元组,而是指新近“合成”的新实体。