ventajas transacciones transaccion tipos propiedades niveles las fundamentos comandos aislamiento sql postgresql transactions sql-insert

tipos - transacciones sql



Obtener valores de RETURNING*dentro de una transacción (2)

Sospecho que está ejecutando todas estas declaraciones como una cadena de texto único del controlador de cliente de su idioma. Si ese es el caso, el resultado devuelto al cliente será lo que devuelva la última declaración en el bloque de declaraciones que envió. En este caso, esa es la declaración COMMIT , que no tiene ningún resultado, por lo que no obtendrá ningún resultado.

Ejecute cada enunciado uno por uno y debería funcionar bien. No puedo dar un ejemplo más detallado porque no ha mencionado qué idioma está utilizando.

Aquí hay un ejemplo de Python / psycopg. El primer enfoque donde todo el SQL se envía en un blob causa una excepción cuando trato de obtener los resultados, porque commit no produce un resultado. El segundo ejemplo, donde ejecuto cada instrucción por separado y obtengo los resultados de la select antes de commit , funciona bien.

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

Salida:

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

Cuando tengo dos INSERT SQL (ver a continuación) dentro de un begin; y commit; transacción entonces el RETURNING * no devuelve nada, pero si saco el begin; y commit; el RETURNING * devuelve el registro insertado.
¿Cómo puedo hacer que el RETURNING * funcione dentro de una transacción?

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;


Una forma sería usar un CTE modificador de datos y empaquetar los dos INSERT s en un solo comando. Requiere PostgreSQL 9.1 o posterior:

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 *;

Sin embargo, recuperas los valores con RETURNING * en cualquier caso. Simplemente COMMIT antes de enviar COMMIT . Enviado como lote, solo se devuelven los resultados del last comando, que sería el resultado de COMMIT , si envía todos los comandos como un solo lote.

Mantenga COMMIT; hasta que haya recibido los resultados del segundo INSERT .

En una función plpgsql

Una función se ejecuta dentro de una transacción automáticamente. No necesita BEGIN / COMMIT explícito. Para reutilizar los valores que obtiene de un INSERT use las RETURNING *expressions* INTO [STRICT] *target* .

Considere esta demostración simple:

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