从事务中的RETURNING*获取值

Joh*_*ell 8 sql postgresql transactions sql-insert

当我有两个INSERT一个内部SQL语句(见下文)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;
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 6

一种方法是使用修改数据的CTE并将两个INSERTs 打包到一个命令中。需要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 *;
Run Code Online (Sandbox Code Playgroud)

但是,无论如何都会获得价值RETURNING *发送之前请先阅读它们COMMIT。批量发送时,仅last返回命令的结果- COMMIT如果您将所有命令作为一批发送,则返回的结果为。

退后一步,COMMIT;直到收到第二个结果INSERT


在plpgsql函数中

函数自动在事务内部运行。您不需要显式的BEGIN / COMMIT。要重用值,您可以从INSERTuse 返回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();
Run Code Online (Sandbox Code Playgroud)


Cra*_*ger 5

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

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

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

输出:

$ python3 test.py 
Failed:  no results to fetch
[(1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,), (9,), (10,)]
Run Code Online (Sandbox Code Playgroud)