11

andトランザクション内に 2 つのINSERTSQL ステートメント (以下を参照)がある場合、は何も返しませんが、 を取り出すと、は挿入されたレコードを返します。をトランザクション内で機能さ せるにはどうすればよいですか?begin;commit;RETURNING *begin;commit;RETURNING *
RETURNING *

BEGIN;

INSERT INTO gis_field_configuration
   (level_unique_name, level_name_caption, use_for_charts, use_as_displayby, 
    displayby_label, data_type, level_help_text)
VALUES (
    '[john].[john]',
    'john',
    'false',
    'false',
    '',
    'text',
    'help text'
);

INSERT INTO gis_field_configuration_bycube
   (cube, level_unique_name)
VALUES (
    'Instruments',
    '[john].[john]'
) RETURNING *;

COMMIT;
4

2 に答える 2

8

1つの方法は、データ変更CTEINSERTを使用して、2つを1つのコマンドにパックすることです。PostgreSQL9.1以降が必要です

WITH x AS (
   INSERT INTO gis_field_configuration (level_unique_name, level_name_caption
                ,use_for_charts, use_as_displayby, displayby_label, data_type
                ,level_help_text)
   VALUES (
       '[john].[john]',
       'john',
       'false',
       'false',
       '',
       'text',
       'help text'
   )
   )
INSERT INTO gis_field_configuration_bycube
   (cube, level_unique_name)
VALUES (
    'Instruments',
    '[john].[john]'
    )
RETURNING *;

ただし、どのような場合でも値を取り戻すことRETURNING *できます。送信する前にそれらを読んでくださいCOMMIT。バッチとして送信されると、コマンドの結果のみが返されます。これは、すべてのコマンドを1つのバッチとして送信した場合lastの結果になります。COMMIT

2番目の結果を受け取るCOMMIT;までお待ちくださいINSERT


plpgsql関数で

関数はトランザクション内で自動的に実行されます。明示的なBEGIN/COMMITは必要ありません。値を再利用するには、INSERT使用から取得しますRETURNING *expressions* INTO [STRICT] *target*

この簡単なデモを考えてみましょう。

CREATE TABLE foo (foo_id serial, bar text);

CREATE OR REPLACE FUNCTION f_foo()
  RETURNS void LANGUAGE plpgsql AS
$BODY$
DECLARE
   foo_var foo; -- type name = table name, fits return type of RETURNING *
   -- or use a generic type record
BEGIN

   INSERT INTO foo (bar)
   VALUES ('baz')
   RETURNING *
   INTO foo_var;

   RAISE NOTICE 'New id is: %', foo_var.foo_id;

   -- do stuff with foo_var

   END;
   $BODY$;

SELECT f_foo();
于 2012-09-17T17:04:12.260 に答える
3

これらすべてのステートメントを、言語のクライアントドライバーからの単一のテキスト文字列として実行していると思われます。その場合、クライアントに返される結果は、送信したステートメントのブロックの最後のステートメントが返すものになります。この場合COMMIT、それは結果がないステートメントなので、結果は返されません。

各ステートメントを1つずつ実行すると、正常に機能するはずです。使用している言語について言及していないため、これ以上詳細な例を示すことはできません。

これがPython/psycopgの例です。すべてのSQLが1つのBLOBで送信される最初のアプローチでは、結果を取得しようとすると例外が発生します。これcommitは、結果が生成されないためです。2番目の例では、各ステートメントを個別に実行し、select前の結果を取得しますが、commit正常に機能します。

import psycopg2

conn = psycopg2.connect("dbname=regress")
curs = conn.cursor();

# All in one blob
try:
    curs.execute("BEGIN; SELECT generate_series(1,10); COMMIT;")
    print(curs.fetchall())
except (psycopg2.ProgrammingError) as ex:
    print("Failed: ", ex)

# vs one-by-one
curs.execute("BEGIN;")
curs.execute("SELECT x.* FROM generate_series(1,10) x;")
print(curs.fetchall())
curs.execute("COMMIT;")

出力:

$ python3 test.py 
Failed:  no results to fetch
[(1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,), (9,), (10,)]
于 2012-09-18T00:49:29.520 に答える