【问题标题】:Cascading a delete to a many-to-many association table?将删除级联到多对多关联表?
【发布时间】:2011-03-15 00:40:02
【问题描述】:

我在级联删除时遇到问题。我有两张桌子,他们 多对多映射:

class File(object): pass 
file_table = Table('file', metadata, 
        Column('id', Integer, primary_key=True, autoincrement=True), 
        Column('filename', String(255)), 
} 

class FileHost(object): pass 
file_host = Table('host', metadata, 
        Column('id', Integer, primary_key=True, autoincrement=True ), 
        Column('name', String(255)), 
) 

file_hosted = Table('file_hosted', metadata, 
        Column('id_host', Integer, ForeignKey('host.id')), 
        Column('id_file', Integer, ForeignKey('file.id')) 
) 

session.mapper(File, file_table, properties={ 
    'host': relation(FileHost, secondary=file_hosted, backref='files', 
                        cascade='all,delete-orphan', single_parent=True) 
}) 
session.mapper(FileHost, file_host) 

这是我得到的错误:

sqlalchemy.exc.IntegrityError: 
(IntegrityError) update or delete on table "file" violates
foreign key constraint "file_hosted_id_file_fkey" on table "file_hosted" 
DETAIL:  Key (id)=(50905) is still referenced from table "file_hosted". 

有人知道我做错了什么吗?

我也问了on the sqlalchemy mailing list的问题,得到了正确答案:

您告诉 SQLAlchemy 将文件删除级联到 FileHost,但是您 想要反过来。您可以通过移动 cascade='all,delete-orphan' 和 single_parent=True 子句放入 反向引用。您可能还想要 uselist=False。

session.mapper(File, file_table, properties={ 
    'host': relation(FileHost, 
                     backref=backref('files', 
                                     cascade='all,delete-orphan', 
                                     single_parent=True), 
                     secondary=file_hosted, 
                     uselist=False) 
}) 

【问题讨论】:

  • 您到底想级联什么:删除File 以删除其FileHost,删除FileHost 以删除其Files,或两者兼而有之?
  • 当我删除 File 时,它应该删除 file_hosted 中的相应行。
  • 能不能加个代码sn-p产生这个错误?
  • 看起来,您的代码很好,应该可以工作。无论如何,为什么你需要一个用于N-to-1 关系的辅助表而不是将ForeignKey 直接放入file 表中?
  • @tom:请添加您的解决方案作为答案。在 SA 中处理订单依赖关系是一个常见问题,人们会喜欢手头的解决方案。

标签: sqlalchemy


【解决方案1】:

应该注意,虽然在这种特殊情况下这不是问题,但如果您在外键声明中未包含 ondelete="CASCADE",您仍然可能会收到此错误。即使在我的关系中声明 cascade="all,delete" 之后,我仍然会收到此错误,直到我添加了 ondelete 属性。您可能还想添加onupdate="CASCADE"

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2015-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-21
  • 1970-01-01
相关资源
最近更新 更多