Извлеченный первичный ключ Обработка ошибок в Python / psycopg2

Использование Python 2.7 и

В [150]: psycopg2. версия Out [150]: '2.4.2 (dt dec pq3 ext)'

У меня есть простые скрипты python, которые обрабатывают транзакции и записывают данные в базу данных. Иногда есть вставка, которая нарушает мой первичный ключ. Это прекрасно, я просто хочу, чтобы он проигнорировал эту запись и продолжал ее веселый путь. Проблема, с которой я столкнулась, заключается в том, что ошибка первичного ключа psycopg2 прерывает весь блок транзакции и все вставки после ошибки. Вот пример ошибки

ERROR: duplicate key value violates unique constraint "encounter_id_pkey" DETAIL: Key (encounter_id)=(9012235) already exists. 

Это будет следующая вставка. не является нарушением.

 Inserting: 0163168~9024065 ERROR: current transaction is aborted, commands ignored until end of transaction block 

Вторая ошибка повторяется для каждой вставки. Вот упрощенный цикл. Я просматриваю кадр данных pandas, но это может быть любой цикл.

 conn = psycopg2.connect("dbname='XXXX' user='XXXXX' host='XXXX' password='XXXXX'") cur = conn.cursor() for i, val in df2.iteritems(): try: cur = conn.cursor() cur.execute("""insert into encounter_id_table ( encounter_id,current_date ) values (%(create_date)s, %(encounter_id)s ) ;""", 'encounter_id':i.split('~')[1], 'create_date': datetime.date.today() }) cur.commit() cur.close() except Exception , e: print 'ERROR:', e[0] cur.close() conn.close() 

И снова основная идея – грациозно обрабатывать Error. В изречении адмирала Нельсона Королевского флота: «Черт, маневры идут прямо на них». Или в нашем случае проклятие Ошибки идут прямо на них ». Я подумал, открыв курсор на каждой вставке, что я бы сбросил транзакционный блок. Я не хочу перезаписывать соединение только из-за ошибки первичного ключа. там что-то я просто не хватает?

Спасибо за руку за ваше время.

Джон

  • Python: количество строк, на которые влияет cursor.execute ("SELECT ...)
  • Комбинированные запросы Django с выражениями
  • Twisted + SQLAlchemy и лучший способ сделать это
  • SQL-запрос работает в консоли, но не в python
  • Каковы реальные уровни абстракции базы данных для Python
  • Как использовать OR с помощью системы фильтров Django?
  • Вставить двоичный файл в базу данных SQLite с помощью Python
  • Как TRUNCATE TABLE с помощью ORM Django?
  • 2 Solutions collect form web for “Извлеченный первичный ключ Обработка ошибок в Python / psycopg2”

    Вы должны откатить транзакцию при ошибке.

    Я добавил еще одну try..except..else конструкцию в коде ниже, чтобы показать точное место, где будет происходить исключение.

     try: cur = conn.cursor() try: cur.execute("""insert into encounter_id_table ( encounter_id,current_date ) values (%(create_date)s, %(encounter_id)s ) ;""", 'encounter_id':i.split('~')[1], 'create_date': datetime.date.today() }) except psycopg2.IntegrityError: conn.rollback() else: conn.commit() cur.close() except Exception , e: print 'ERROR:', e[0] 

    Прежде всего: CURRENT_DATE является зарезервированным словом в каждом стандарте SQL, а также в PostgreSQL. Вы не можете использовать его как идентификатор без двойного цитирования. Я бы настоятельно советовал не использовать его вообще. Я переименовал столбец в curdate в моем примере

    Далее, я не эксперт в синтаксисе python, но вы, похоже, изменили порядок своих столбцов-вставок:

     (%(create_date)s, %(encounter_id)s ) 

    Должно быть:

     ( %(encounter_id)s, %(create_date)s) 

    На ваш главный вопрос: вы можете вообще избежать проблемы, проверяя, находится ли ключ в таблице перед его использованием в команде insert:

     INSERT INTO encounter_id_table (encounter_id, curdate) SELECT 1234, now()::date WHERE NOT EXISTS (SELECT * FROM encounter_id_table t WHERE t.encounter_id = 1234); 

    В синтаксисе Python это должно быть:

     cur.execute("""INSERT INTO encounter_id_table (encounter_id, curdate) SELECT %(encounter_id)s, %(create_date)s, WHERE NOT EXISTS ( SELECT * FROM encounter_id_table t WHERE t.encounter_id = %(encounter_id)s);""", {'encounter_id':i.split('~')[1], 'create_date': datetime.date.today()}) 
    Python - лучший язык программирования в мире.