¿Un COMMIT funciona dentro de una función anónima plgpsql en PostgreSQL 9.5?

8

Estoy importando una gran cantidad de archivos grandes en varias tablas para ser particionadas usando bucles dentro de un bloque de código plpgsql anónimo $do$.

$do$
BEGIN
    FOR yyyy in 2012..2016 THEN 
        EXECUTE $$COPY table$$||yyyy||$$ FROM 'E:\data\file$$||yyyy||$$.csv DELIMITER ',' CSV;$$;
    END LOOP;
END;
$do$ LANGUAGE plpgsql

Todo este proceso debería tomar alrededor de 15 horas y espero que todas las importaciones no se reviertan si hay un error de importación en algún momento.

IIRC COMMITno funciona dentro de las funciones almacenadas porque toda la función se trata como una sola transacción.

De la documentación para$do$

El bloque de código se trata como si fuera el cuerpo de una función sin parámetros, que devuelve nulo. Se analiza y ejecuta una sola vez.

Supongo que esto significa que la totalidad $do$es una transacción, por lo que las confirmaciones dentro del bloque no funcionarán. ¿Estoy en lo correcto?

Rafael
fuente
1
Probar BEGINo COMMITen el cuerpo de la función. Obtendrá una excepción, porque eso no está permitido (no es posible).
Erwin Brandstetter

Respuestas:

9

No,

No puede controlar una transacción dentro de una plpgsqlfunción (o bloque anónimo).

La única opción que tiene es crear una transacción fuera del bloque, por ejemplo:

BEGIN;

DO $$
  -- function stuff

  -- but if you use a exception, you will force a rollback
  RAISE EXCEPTION 'message';
$$ LANGUAGE 'plpgsql';

COMMIT; -- OR ROLLBACK

Por cierto, DO BLOCKStienen el mismo efecto que funciona quién regresa void.

Por favor, vea más en el documento:

Sebastian Webber
fuente
¿Sabemos si este sigue siendo el caso? Tengo una función que necesita recorrer varios cientos de veces. El primer bucle tarda 2 segundos después de que el 7º esté cerca de una hora y no he visto nada después del 10º bucle.
Dennis Bauszus
1

La única solución para comprometerse dentro de los bloques (o funciones) "DO" (para la versión Postgresql anterior a la 11) es usar la conexión dblink al mismo servidor y ejecutar sus consultas allí. Solo tenga en cuenta las variables y la visibilidad de los objetos temporales.

más información sobre dblink Comenzar con el control de transacciones Postgresql-11 desde el interior del bloque "DO" está disponible mientras "DO-block" no se está ejecutando dentro de otra transacción.

Dzhureedzh
fuente
postgresql.org/docs/11/sql-do.html establece que 'las declaraciones de control de transacciones solo se permiten si DO se ejecuta en su propia transacción'. Por supuesto, esto no era cierto con 9.5. OTOH con dblinkusted abrirá otra transacción, por lo que su COMMITllamada no afectará la transacción de la llamada, si no me equivoco.
dezso
Culpa mía. El control de transacciones dentro de "DO" se introdujo en Postgresql-11. Acabo de comprobar en 10.4 todavía no funciona.
Dzhureedzh
@dezso Gracias por señalarme esto, estaba usando el método dblink incluso en servidores PG11.
Dzhureedzh