是否有可能在 postgres 中捕获外键违规

chr*_*ris 5 postgresql psycopg2

我正在尝试将数据插入具有外键约束的表中。如果在我插入的行中存在约束违规,我想删除该数据。

问题是每次我违反约束时,postgres 都会返回一个错误。我是否可以在插入语句中包含一些语句,例如“ON FOREIGN KEY CONSTRAINT DO NOTHING”?

编辑:

这是我正在尝试执行的查询,其中 info 是一个字典:

cursor.execute("INSERT INTO event (case_number_id, date, \
session, location, event_type, worker, result) VALUES \
(%(id_number)s, %(date)s, %(session)s, \
%(location)s, %(event_type)s, %(worker)s, %(result)s) ON CONFLICT DO NOTHING", info)
Run Code Online (Sandbox Code Playgroud)

当存在外键违规时会出错

Kev*_*vin 4

如果一次只插入一行,则可以在插入之前创建一个保存点,并在插入失败时回滚到该保存点(或在插入成功时释放它)。

对于 Postgres 9.5 或更高版本,您可以使用INSERT ... ON CONFLICT DO NOTHINGwhich 执行它所说的操作。您可以编写ON CONFLICT DO UPDATE SET column = value...,这会自动将您的插入转换为与您冲突的行的更新(此功能有时称为“upsert”)。

这不起作用,因为 OP 正在处理外键约束而不是唯一约束。在这种情况下,您可以最轻松地使用我之前描述的保存点方法,但对于多行,它可能会很乏味。如果您需要一次插入多行,那么将它们拆分为多个插入语句应该具有合理的性能,前提是您没有在自动提交模式下工作,所有插入都发生在一个事务中,并且您没有插入大量行。

有时,您确实需要在单个语句中进行多次插入,因为与数据库通信的往返开销加上每次插入上都有保存点的成本实在太高了。在这种情况下,有许多不完善的方法。最不糟糕的可能是构建一个嵌套查询,它选择您的数据并将其与另一个表连接起来,如下所示:

INSERT INTO table_A (column_A, column_B, column_C)
SELECT A_rows.*
FROM VALUES (...) AS A_rows(column_A, column_B, column_C)
JOIN table_B ON A_rows.column_B = table_B.column_B;
Run Code Online (Sandbox Code Playgroud)