Как я могу получить количество строк в зависимости от psycopg2 connection.commit()?

В настоящее время у меня есть следующий метод для выполнения инструкций INSERT/UPDATE/DELETE с помощью psycopg2 в Python:

def exec_statement(_cxn, _stmt):
    try:
        db_crsr = _cxn.cursor()
        db_crsr.execute(_stmt)
        _cxn.commit()
        db_crsr.close()
        return True
    except:
        return False

Но мне бы хотелось, чтобы вместо bool было возвращено количество строк, на которое повлияла транзакция, или -1, если операция завершилась неудачно.

Есть ли способ получить количество строк, затронутых _cxn.commit()? Например. для единственного INSERT всегда было бы 1, для DELETE или UPDATE, количеством строк, на которые повлияла инструкция и т.д.?

Ответы

Ответ 1

commit() не может использоваться для подсчета строк, но вы можете использовать курсор для получения этой информации после каждого вызова execute. Вы можете использовать его атрибут rowcount, чтобы получить количество строк, затронутых для SELECT, INSERT, UPDATE и DELETE.

то есть.

    db_crsr = _cxn.cursor()
    db_crsr.execute(_stmt)

    rowcount = db_crsr.rowcount;

    _cxn.commit()
    db_crsr.close()

    return rowcount

Если вы хотите вернуть число затронутых строк, я бы порекомендовал не перехватывать никаких исключений, так как если операция действительно не удалась (скажем, запрос был искажен, или было нарушение ограничений FK и т.д.), исключение должно быть поднятым, и в этом случае вызывающий может поймать это и вести себя по своему желанию. (Или, если вы хотите централизовать обработку исключений, возможно, raise пользовательское исключение MyPostgresException или подобное.)

-1 может быть возвращен в случае отсутствия отказа в определенных ситуациях (http://initd.org/psycopg/docs/cursor.html#cursor.rowcount), поэтому я бы рекомендовал не использовать это значение как индикатор отказа. Если вы действительно хотите вернуть числовое значение в случае сбоя, возможно, вернем число, подобное -10, будет работать (в блоке except), так как rowcount никогда не должно возвращать это.