2

I'm trying to import multiple rows into my SQL table which has 'id' as a unique constraint, which s supposed to get rejected by SQL insert due to constraint violation.

I'm using PostgreSQL

Assuming my data are

   records_to_insert = [ [2,'Jon','2018-01-11', 26] ,
                         [3,'Jane','2017-12-11', 27],
                         [4,'Bill','2018-03-23', 26] ]

and in the database I ALREADY HAVE

2,'Jon','2018-01-11', 26

So now if I do

   cur = db_conn.cursor()
    cur.execute("SAVEPOINT bulk_savepoint")
    try:
        cur.executemany("INSERT INTO  mytable VALUES (%s,%s,%s,%s);", records_to_insert )
    except:
        cur.execute("ROLLBACK TO SAVEPOINT bulk_savepoint")

    db_conn.commit()

Because the rows have one row that violates my constraint, it does not insert the rest of the rows which do not violate the id constraint and nothing gets inserted,

how can I insert the rows that do not violate the constraint without looping through the list? I have huge data that I'm going to import and looping through each element will take a long time.

Thanks.

5
  • Thanks, it's extremely slow as I'm using a cloud database. I'm sure there is a way to do it as I have done this before, Commented Feb 25, 2019 at 19:01
  • Looks like you got an answer. Commented Feb 25, 2019 at 19:02
  • I think it's only for MySQL which I do not use, I'm working with PostgreSQL. Commented Feb 25, 2019 at 19:12
  • I just updated my answer for PostgreSQL. In the future, tag your answer with the database engine you're using and then people can curate their answers to your setup. Commented Feb 25, 2019 at 19:21
  • Is this id in the file relevant? Meaning that this of column often depends on insertion order so Jon (id=3) in one file might be at id=4 in another. If you dont know you could just leave out the id in the insert and it would just get autogenerated by postgres. Really depends on your data, your feeds and foreign key considerations. Commented Feb 25, 2019 at 22:19

1 Answer 1

3

You're looking for INSERT IGNORE

change

cur.executemany("INSERT INTO mytable VALUES (%s,%s,%s,%s);", records_to_insert )

to

cur.executemany("INSERT IGNORE INTO mytable VALUES (%s,%s,%s,%s);", records_to_insert )

For PostgreSQL use ON CONFLICT DO NOTHING

cur.executemany("""
INSERT INTO mytable VALUES (%s,%s,%s,%s)
ON CONFLICT DO NOTHING;""", records_to_insert )
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I'm using PostgreSQL and the ignore case is not working there :(
On PostgreSQL you can use ON CONFLICT DO NOTHING postgresqltutorial.com/postgresql-upsert. I'm updating my answer to reflect that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.