【问题标题】:IntegrityError: foreign key violation upon deleteIntegrityError:删除时违反外键
【发布时间】: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?
  • 为什么要删除有发货的订单?通常,这是您希望失败的事情。您永远都不想删除实际发货。
  • 好吧,因为这个订单还没有提交。这是下订单用例的一部分,当有人从订单中删除所有商品时,我只需删除订单并重定向回空购物车。

标签: sql database django postgresql django-models


【解决方案1】:

详细信息:键 (id)=(45) 仍然是 从表“main_shipment”中引用。

仍然有一条引用 id 45 的记录。您之前确实删除了 main_shipment 中的记录 17,但可能还有其他记录。您必须删除 main_shipment 中引用 main_order 中 id 45 的所有记录。如果没有,数据库会保护您免受对数据的损害。

【讨论】:

  • Ahhhhhh :/ 我和它斗争了这么久,我才意识到后来在 python 代码中,在更高的代码块中,我有 shipping.save() :/ 我没有注意到它conn.queries 输出,因为它是在调用 shipping.save() 之前打印的。
猜你喜欢
  • 1970-01-01
  • 2021-05-09
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 2015-08-19
  • 2020-03-27
  • 2012-11-27
相关资源
最近更新 更多