从事务中的RETURNING *获取值

时间:2012-09-17 16:53:32

标签: sql postgresql transactions sql-insert

当我在INSERTbegin;事务中有两个commit; SQL语句(见下文)时,RETURNING *不会返回任何内容,但如果我取出{ {1}}和begin; commit;确实会返回插入的记录 如何让RETURNING *在交易中工作?

RETURNING *

2 个答案:

答案 0 :(得分:5)

一种方法是使用data-modifying CTE并将两个INSERT打包成一个命令。需要PostgreSQL 9.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之前在中阅读它们。作为批处理发送,如果您将所有命令作为一个批次发送,则仅返回last命令的结果 - 这是COMMIT的结果。

请等待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();

答案 1 :(得分:1)

我怀疑您将所有这些语句作为语言客户端驱动程序中的单个文本字符串运行。如果是这种情况,返回给客户端的结果将是您发送的语句块中的最后一个语句返回的结果。在这种情况下,COMMIT语句没有结果,所以你没有得到任何结果。

逐个运行每个语句,它应该可以正常工作。我无法提供更详细的示例,因为您还没有提到您正在使用哪种语言。

这是一个Python / psycopg示例。当我尝试获取结果时,第一种在一个blob中发送所有SQL的方法会导致异常,因为commit没有产生结果。第二个示例,我单独运行每个语句并在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,)]