【问题标题】:SQL continue executing queries after duplicate key violationSQL 在重复键违规后继续执行查询
【发布时间】:2010-06-26 05:44:35
【问题描述】:

我有一种情况,如果它不存在我想插入一行,如果它已经存在则不插入它。我尝试创建防止这种情况发生的 sql 查询(请参阅here),但有人告诉我一个解决方案是创建约束并在违反它们时捕获异常。

我已经设置了限制。我的问题是 - 我怎样才能捕捉到异常并继续执行更多查询?如果我的代码如下所示:

cur = transaction.cursor()

#execute some queries that succeed

try:
    cur.execute(fooquery, bardata)  #this query might fail, but that's OK
except psycopg2.IntegrityError:
    pass

cur.execute(fooquery2, bardata2)

然后我在第二次执行时出错:

psycopg2.InternalError: current transaction is aborted, commands ignored until end of transaction block

如何告诉计算机我希望它继续执行查询?我不想transaction.commit(),因为我可能想回滚整个事务(之前成功的查询)。

【问题讨论】:

  • 我会推荐你​​的第一种方法。我认为数据库只插入不存在的行的工作要少得多。捕捉错误需要先完成工作,然后再取消,这大约是两倍的工作量。如果您一次只添加一条记录,我明白这个想法,但对于多条记录或数千条记录,我认为您最好采用第一种方式。话虽如此,我对您当前的问题没有任何有用的答案。
  • @MJB:它只会在发生错误时导致更多的工作。如果插入没有错误,那么它是一帆风顺的。因此,这取决于您是否期望获得重复密钥违规或不获得重复密钥违规会更常见。针对更常见的情况进行优化。
  • 我希望经常有重复的密钥违规,所以我想这回答了我的问题!
  • @Bill:我同意规划更常见的方法。我之所以发表评论,是因为 OP 似乎还没有提供信息。现在看来是。

标签: sql database postgresql


【解决方案1】:

我认为您可以做的是在尝试执行可能导致违规的语句之前使用SAVEPOINT。如果发生违规,您可以回滚到SAVEPOINT,但保留您的原始交易。

这是另一个可能有用的线程: Continuing a transaction after primary key violation error

【讨论】:

    【解决方案2】:

    我对 SAVEPOINT 答案投了赞成票——尤其是因为它链接到我的答案被接受的问题。 ;)

    但是,鉴于您在 cmets 部分中的陈述,您“经常”预计会出现错误,我可以建议另一种选择吗?

    此解决方案实际上可以追溯到您的其他问题。这里的区别在于如何将数据快速加载到正确的位置和格式,以便在单个 SELECT 周围移动数据 - 并且 - 对于您要填充的任何表都是通用的(因此相同的代码可以用于多个不同的表)。这是我如何在纯 PostgreSQL 中执行此操作的粗略布局,假设我有一个与要插入的表格式相同的 CSV 文件:

    CREATE TEMP TABLE input_file (LIKE target_table);
    
    COPY input_file FROM '/path/to/file.csv' WITH CSV;
    
    INSERT INTO target_table
    SELECT * FROM input_file
    WHERE (<unique key field list>) NOT IN (
        SELECT <unique key field list>
        FROM target_table
    );
    

    好的,这是一个理想化的示例,我还忽略了几件事(例如报告重复项、通过 Python 内存数据将数据推送到表中、从 STDIN 复制而不是通过文件等)。 ),但希望基本的想法是存在的,如果您期望被拒绝的记录多于接受的记录,它将避免大部分开销。

    【讨论】:

    • hmm 有趣.. COPY 可能是我要找的东西
    猜你喜欢
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2012-07-27
    相关资源
    最近更新 更多