关于sql:无法从postgres中的UPDATE RETURNING子句中选择

Cannot SELECT from UPDATE RETURNING clause in postgres

我将问题与更复杂的查询隔离开来。 这里是测试场景

1
2
3
4
5
6
7
8
DROP TABLE test;
CREATE TABLE test (
  id INTEGER,
  description VARCHAR(100)
);

INSERT INTO test(id, description) VALUES (1,'new');
INSERT INTO test(id, description) VALUES (2,'new');

如果我运行查询:

1
SELECT * FROM test WHERE id IN (UPDATE test SET description='test' RETURNING id)

我收到以下错误:

错误:"test"或其附近的语法错误
第1行:SELECT * FROM测试WHERE id(UPDATE测试集描述='测试'RE ...
^

*** Fehler ***

错误:"test"或其附近的语法错误
SQL状态:42601
贼臣:37

但是,如果我只运行国家政府

1
UPDATE test SET VALUE='test' RETURNING id

我得到一个2行的结果:

1
2

如果我代表结果,我会有一个查询,如:

1
SELECT * FROM test WHERE id IN (1,2);

结果:

1;"测试"
2;"测试"

为什么我的初始陈述没有得到相同的结果?


在PostgreSQL 9.1 INSERT / UPDATE / DELETE之前只能用作顶级语句。这就是您收到语法错误的原因。

从9.1开始,您可以将数据修改语句与公用表表达式一起使用。您的示例查询将如下所示:

1
2
WITH updated AS (UPDATE test SET description = 'test' RETURNING id)
SELECT * FROM test WHERE id IN (SELECT id FROM updated);

从刚刚修改过的表中进行选择时要小心。你可以这样得到令人困惑的结果。因为查询是在同一个快照中执行的,SELECT不会看到UPDATE语句的效果。


您在UPDATE查询中更新两行,添加WHERE子句以限制受影响的行。

1
UPDATE test SET description = 'test' WHERE id = 1 RETURNING id

返回单行。


你错过了IN... WHERE id IN (UPDATE ...吗?

However if I only run the statemennt"UPDATE test set value='test'
RETURNING id", I get a result with 2 rows. Why is that?

您的UPDATE没有WHERE子句,因此它会更新每一行,其中有两行。


1
UPDATE test SET description='test' RETURNING *

会给你初始查询所期望的结果集。

但我怀疑你在尝试更复杂的东西?


你不是限制你的where子句。你需要id =(blahblah)或id IN(blahblah)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
DROP TABLE IF EXISTS test_tab;

CREATE TABLE test_tab (
  id INTEGER,
  description VARCHAR(100)
);

INSERT INTO test_tab(id, description) VALUES (1,'new');
INSERT INTO test_tab(id, description) VALUES (2,'new');

SELECT * FROM test_tab;

DO $$
DECLARE
    myID    test_tab.id%TYPE;
    testID  test_tab.id%TYPE;
    cur_IDs CURSOR FOR SELECT id FROM test_tab;
BEGIN
    OPEN cur_IDs;
    LOOP
        FETCH cur_IDs INTO testID;
        EXIT WHEN testID IS NULL;

        UPDATE test_tab SET description='test' WHERE id = testID RETURNING id INTO myID;
        raise notice 'myID %', myID;
    END LOOP;
    CLOSE cur_IDs;
END$$;


DROP TABLE IF EXISTS test_tab;


我是从Ants Aasma中添加的,如果在同一张桌子上选择,使用:

1
2
WITH updated AS (UPDATE test SET description = 'test' RETURNING id, description)
SELECT * FROM updated;