2011-08-25 54 views
9

我將問題從更復雜的查詢中分離出來。這裏的測試場景無法從UPDATE RETURNING子句中選擇postgres

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'); 

如果我運行查詢:

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

,我發現了以下錯誤:

錯誤:語法錯誤或接近 「測試」 LINE 1: SELECT * FROM test WHERE id(UPDATE test set description ='test'RE ... ^

*** Fehler ** *

錯誤:在語法錯誤或接近 「測試」 SQL狀態:42601 賊臣:37

但是如果我只運行statemennt

UPDATE test set value='test' RETURNING id 

我得到2行的結果:

如果我分別代替該結果我會像的查詢:

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

其結果:

1; 「測試」 2; 「測試」

爲什麼我的初始陳述沒有得到同樣的結果?

+1

他們必須是獨立的語句。兩行正在更新的事實可能會導致問題,當多個行/值返回時,從未嘗試返回。 –

回答

23

在PostgreSQL 9.1之前INSERT/UPDATE/DELETE只能用作頂級語句。這就是爲什麼你得到一個語法錯誤。

從9.1開始,您可以使用具有通用表表達式的數據修改語句。您的示例查詢如下所示:

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

從剛剛修改的表中進行選擇時要小心。你可以通過這種方式得到混亂的結果。因爲查詢是在同一個快照中執行的,所以SELECT不會看到UPDATE語句的效果。

+2

僅供參考,CTE方法不適用於INSERT –

+0

因此,此'SELECT'將返回id和舊描述值'new',而不是更新後的值'test'? – Davos

6

您更新了UPDATE查詢中的兩行,添加了WHERE子句來限制受影響的行。

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

返回一個單列

+0

SELECT * FROM test WHERE id IN(UPDATE test SET value ='test'WHERE id = 1 TURNING id)shows the same error – markus

+0

updated「value」to「description」,same issue – markus

3

你錯過了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條款,因此它更新的每一行,其中有兩個。

+0

yes,just updated it – markus

+0

問題是而不是更新RETURNING,即使用和不使用where子句。問題在於選擇它。 – markus

1

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

1
UPDATE test set description='test' RETURNING * 

會爲您提供您期望從初始查詢得到的結果集。

但我懷疑你是在嘗試一些更復雜的東西?

0
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; 
-1

我從螞蟻Aasma此外,如果選擇在同一個表,使用:

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