sql >> Base de Datos >  >> RDS >> PostgreSQL

Continuar una transacción después de un error de violación de clave principal

También puede usar SAVEPOINTs en una transacción.

El pseudocódigo Pythonish se ilustra desde el lado de la aplicación:

database.execute("BEGIN")
foreach data_row in input_data_dictionary:
    database.execute("SAVEPOINT bulk_savepoint")
    try:
        database.execute("INSERT", table, data_row)
    except:
        database.execute("ROLLBACK TO SAVEPOINT bulk_savepoint")
        log_error(data_row)
        error_count = error_count + 1
    else:
        database.execute("RELEASE SAVEPOINT bulk_savepoint")

if error_count > error_threshold:
    database.execute("ROLLBACK")
else:
    database.execute("COMMIT")

Editar:aquí hay un ejemplo real de esto en acción en psql basado en una ligera variación del ejemplo en la documentación (instrucciones SQL con el prefijo ">"):

> CREATE TABLE table1 (test_field INTEGER NOT NULL PRIMARY KEY);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "table1_pkey" for table "table1"
CREATE TABLE

> BEGIN;
BEGIN
> INSERT INTO table1 VALUES (1);
INSERT 0 1
> SAVEPOINT my_savepoint;
SAVEPOINT
> INSERT INTO table1 VALUES (1);
ERROR:  duplicate key value violates unique constraint "table1_pkey"
> ROLLBACK TO SAVEPOINT my_savepoint;
ROLLBACK
> INSERT INTO table1 VALUES (3);
INSERT 0 1
> COMMIT;
COMMIT
> SELECT * FROM table1;  
 test_field 
------------
          1
          3
(2 rows)

Tenga en cuenta que el valor 3 se insertó después del error, ¡pero aún dentro de la misma transacción!

La documentación de SAVEPOINT se encuentra en http://www.postgresql.org/docs/8.4/static/sql-savepoint.html.