IntegrityError:删除时违反外键
Posted
技术标签:
【中文标题】IntegrityError:删除时违反外键【英文标题】:IntegrityError: foreign key violation upon delete 【发布时间】:2011-02-02 08:40:59 【问题描述】:我有订单和发货模型。 Shipment 有一个 Order 的外键。
class Order(...):
...
class Shipment()
order = m.ForeignKey('Order')
...
现在,在我的一个观点中,我想删除订单对象以及所有相关对象。所以我调用 order.delete()。
我有 Django 1.0.4、PostgreSQL 8.4 并且我使用事务中间件,所以整个请求都包含在单个事务中。
问题是在 order.delete() 我得到:
...
File "/usr/local/lib/python2.6/dist-packages/django/db/backends/__init__.py", line 28, in _commit
return self.connection.commit()
IntegrityError: update or delete on table "main_order" violates
foreign key constraint "main_shipment_order_id_fkey" on table "main_shipment"
DETAIL: Key (id)=(45) is still referenced from table "main_shipment".
我在 connection.queries 中检查了正确的查询以正确的顺序执行。第一批货物被删除,之后 django 对订单行执行删除:
'time': '0.000', 'sql': 'DELETE FROM "main_shipment" WHERE "id" IN (17)',
'time': '0.000', 'sql': 'DELETE FROM "main_order" WHERE "id" IN (45)'
外键具有 ON DELETE NO ACTION(默认)并且最初是延迟的。我不知道为什么会违反外键约束。
我也尝试注册 pre_delete 信号并在调用 delete on order 之前手动删除货件对象,但它导致了同样的错误。
我可以在 Postgres 中更改此键的 ON DELETE 行为,但这只是一个 hack,我想知道是否有人对这里发生的事情有更好的了解。
还有一个小细节,我的 Order 模型继承自 Cart 模型,所以它实际上没有 id 字段而是 cart_ptr_id 并且在 order 上执行 DELETE 后,cart 上也有 DELETE,但似乎无关?到发货->订单问题,所以我在示例中对其进行了简化。
【问题讨论】:
好吧,我在 psql 控制台中尝试过,结果相同,所以严格来说是 postgreql 问题。再见,我不明白 deferred 的工作原理。 能否提供相关的建表SQL? 为什么要删除有发货的订单?通常,这是您希望失败的事情。您永远都不想删除实际发货。 好吧,因为这个订单还没有提交。这是下订单用例的一部分,当有人从订单中删除所有商品时,我只需删除订单并重定向回空购物车。 【参考方案1】:详细信息:键 (id)=(45) 仍然是 从表“main_shipment”中引用。
仍然有一条引用 id 45 的记录。您之前确实删除了 main_shipment 中的记录 17,但可能还有其他记录。您必须删除 main_shipment 中引用 main_order 中 id 45 的所有记录。如果没有,数据库会保护您免受对数据的损害。
【讨论】:
Ahhhhhh :/ 我和它斗争了这么久,我才意识到后来在 python 代码中,在更高的代码块中,我有 shipping.save() :/ 我没有注意到它conn.queries 输出,因为它是在调用 shipping.save() 之前打印的。以上是关于IntegrityError:删除时违反外键的主要内容,如果未能解决你的问题,请参考以下文章
IntegrityError 在表“orders_order”上插入或更新违反外键约束“
Flask中的(pymysql.err.IntegrityError)(1451,'无法删除或更新父行:外键约束失败...')