Continuing a transaction after primary key violation error

前端 未结 4 1051
旧巷少年郎
旧巷少年郎 2020-11-30 07:56

I am doing a bulk insert of records into a database from a log file. Occasionally (~1 row out of every thousand) one of the rows violates the primary key and causes the tran

4条回答
  •  甜味超标
    2020-11-30 08:33

    You can also use SAVEPOINTs in a transaction.

    Pythonish pseudocode is illustrate from the application side:

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

    Edit: Here's an actual example of this in action in psql based on a slight variation of the example in the documentation (SQL statements prefixed by ">"):

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

    Note that the value 3 was inserted after the error, but still inside the same transaction!

    The documentation for SAVEPOINT is at http://www.postgresql.org/docs/8.4/static/sql-savepoint.html.

提交回复
热议问题