2011-08-25 20 views
9

これは、はるかに複雑なクエリから問題を除外します。ここではテストシナリオpostgresのUPDATE RETURNING句からSELECTできません

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) 

私は次のエラーを取得しています:

ERROR:構文でエラーまたは近くに "テスト" LINE 1: SELECT * FROMテストWHERE id(更新テストセットの説明= 'テスト' RE ... ^

*** Fehler ** *

ERROR:構文エラーまたはその付近 "テスト" SQLステータス:42601 ゼッケン:37

しかし、私は唯一のstatemennt

を実行する場合

:私は2行との結果を得
UPDATE test set value='test' RETURNING id 

私はその結果をsubstitude場合は私のようなクエリなければなりません。結果

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

1; "テスト" 2; "テスト"

を私は最初の声明で同じ結果を得ないのはなぜですか?

+1

を彼らは別々のステートメントでなければなりません。 2つの行が更新されているという事実により、問題が発生する可能性があります。複数の行/値が戻ってきたときには、RETURNINGを試みることはありません。 –

答えて

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

FYI、CTEのアプローチはINSERT –

+0

で動作しないので、この 'SELECT'はidと古い記述値' 'new''を代わりに' 'test''で更新しますか? – Davos

6

UPDATEクエリで2行を更新し、影響を受ける行を制限するためにWHERE句を追加します。 単一行を返す

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

+0

SELECT * FROMテストのWHERE IDは、UPDATEテストのSET値= 'テスト' WHERE id = 1 TURNING id)は同じエラーを示します – markus

+0

は「値」を「説明」に更新しました。同じ問題 – 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句を持っていないので、この2つがあり、そのうちのすべての行を更新します。

+0

はい、ちょうど更新しました – markus

+0

更新RETURNINGではなく、where句を使用して作業しています。問題はその周辺の選択です。 – markus

1

where句は制限されません。あなたはid =(blahblah)かid(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; 
関連する問題