使用Python 2.7和
In [150]:psycopg2.versionOut[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 Dataframe ,但它可以是任何循环。
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()
同样,基本的想法是优雅地处理错误。皇家海军上将纳尔逊(Admiral Nelson)曾说过:“该死的演习直接向他们冲去”。或者在我们的情况下,该死的错误直接指向他们。”我想通过在每个插入上打开一个光标,我将重置事务块。我不想仅仅因为一个主键错误而必须重置连接。是不是有什么我刚刚错过了?
感谢您的时间。
约翰
2条答案
按热度按时间anhgbhbe1#
您应该在出现错误时回滚事务。
我在下面的代码中添加了一个
try..except..else
结构,以显示异常发生的确切位置。polkgigr2#
首先:
CURRENT_DATE
是每个SQL标准以及PostgreSQL中的保留字。如果没有双引号,则不能将其用作标识符。我宁愿避免这种情况,因此在示例中使用列名curdate
。接下来,您似乎颠倒了插入列的顺序:
应为:
回答你的主要问题:完全避免这个问题!
因为Postgres 9.5
INSERT ... ON CONFLICT DO NOTHING
是要走的路。这也避免了并发写入负载下的竞争条件:参见:
在Python语法中,应该是:
在旧版本中,你可以通过在插入键之前检查它是否已经在表中来避免这个问题:
但在并发写负载下可能会失败。