如何在executemany中自动跳过重复的raw?

时间:2014-09-11 15:56:57

标签: python postgresql psycopg2

我为我的表设置了一个主键。现在我想在executemany Insert时自动跳过重复的raw。 我该怎么办?这是我的代码和评论。谢谢你们。

cmd = \
'''
CREATE TABLE test(
id INTEGER PRIMARY KEY NOT NULL,
value INTEGER
)
'''
c.execute(cmd)
# now we have key = 1,2,3,4
c.executemany("INSERT INTO test VALUES (%s,%s)", [(1,100),
                                                  (3,100),
                                                  (2,100),
                                                  (4,100),])
# I want script automatically skip repeated row (1,200)
# if I add a try, except here, only the (5, 100) has been inserted
# because script jump out when exception raised
c.executemany("INSERT INTO testVALUES (%s, %s)", [(5,100),
                                                  (1,200),
                                                   (6,100)])

1 个答案:

答案 0 :(得分:0)

如果您想使用这种INSERT语法,我建议您使用executemany,在循环内使用execute,并在每次commit之后使用commit一个(因为如果你没有conn,你将在异常发生后丢失以前插入的项目。)

类似(for item_tuple in [(1,100), (3,100), (2,100), (4,100)]: try: c.execute("INSERT INTO test VALUES (%s,%s)", item_tuple[0], item_tuple[1]) conn.commit() except Exception as e: print "failed to insert: {0}".format(e) conn.rollback() # continue on to next item 是你的连接对象):

rollback

这样,你可以继续,吞下(并打印)异常(如果需要,你可以使用正则表达式来搜索异常文本以获得更窄的字符串,这样你就不会吞下每个异常,因为这样做在某些情况下可能是不受欢迎的),然后commit这样你就可以继续使用连接了(否则你会得到一个关于尝试使用与中止事务的连接的错误)。 / p>

另一个选项,不一定要求您对每个项目INSERT

你可以使用SELECT形式作为输入,for item_tuple in [(1,100), (3,100), (2,100), (4,100)]: c.execute("INSERT INTO test VALUES (%s,%s) SELECT %s, %s WHERE NOT EXISTS (SELECT 1 FROM test WHERE value = %s )", item_tuple[0], item_tuple[1], item_tuple[0], item_tuple[1], item_tuple[1]) 语句作为输入,你可以构造它以便选择所需的值,但检查它们是否已经存在,所以如果是,则select的结果为空集,并且不会插入任何内容。 (由于 MVCC ,这可能会在多个连接和事务的情况下出现问题,但如果您是唯一一个为了此检查而插入表中的人,则应该没问题)。

所以,像这样:

{{1}}