根据条件插入行

时间:2016-07-01 01:00:55

标签: postgresql psycopg2

我有一个postgres表,用于保存用户文件。两个用户可以拥有一个具有相同名称的文件,但不允许用户拥有两个具有相同名称的文件。目前,如果用户尝试上传具有已使用名称的文件,则数据库将按原样吐出错误。

  

IntegrityError:重复键值违反了唯一约束" file_user_id_title_key"

我想要做的是首先使用文件名和用户ID查询数据库,以查看用户是否正在使用文件名。如果名称已被使用,则返回错误,否则写入行。

cur.execute('INSERT INTO files(user_id, title, share)'
            'VALUES (%s, %s, %s) RETURNING id;',
            (user.id, file.title, file.share))

1 个答案:

答案 0 :(得分:0)

问题是如果不打开竞争条件就不能真正做到这一点:
没有什么可以阻止其他人在您查询表和尝试插入行之间插入冲突行,因此错误仍然可能发生(除非您采取极端措施,例如在执行此操作之前锁定表,这会严重影响并发性。)

此外,您提出的技术会通过添加多余的第二个查询来增加数据库的负载。

你是对的,你不应该用数据库错误消息对付用户,但正确的处理方法如下:

  • INSERT就像您展示的新行一样。
  • 检查是否收到错误。
  • 如果错误的SQLSTATE是SQL标准值23505(unique_violation),您知道用户已经有这样的文件并向用户显示相应的错误。

因此,您可以将INSERT语句视为原子操作检查是否已有匹配的条目,如果没有,则添加行