【问题标题】:SQLAlchemy Delete Cascade Integrity ErrorSQLAlchemy 删除级联完整性错误
【发布时间】:2015-06-09 03:50:46
【问题描述】:

我正在尝试从我的数据库中删除deleteorder,同时删除与之相关的所有ordereditems

with contextlib.closing(DBSession()) as session:
    try:
        returnedOrder = session.query(ORDER).filter_by(ORDERSID=orderID).first()
        session.delete(returnedOrder)
        session.commit()
    except exc.SQLAlchemyError, error:
        session.rollback()
        raise_database_error(error)
    else:
        return '1'

这里是相关的classes(部分项目已被删除):

class ORDER(Base):
    __tablename__ = 'ORDERS'

    ORDERSID = Column(Integer, primary_key=True)
    ORDERSCOST = Column(Numeric(19, 4), nullable=False)

    ORDEREDITEM = relationship("ORDEREDITEM")  


class ORDEREDITEM(Base):
    __tablename__ = 'ORDEREDITEMS'
    __table_args__ = (
        Index('AK_ORDERSID_ITEMID', 'ORDERSID', 'ITEMSID', unique=True),
    )

    ORDEREDITEMSID = Column(Integer, primary_key=True)
    ITEMSID = Column(ForeignKey(u'ITEMS.ITEMSID'), nullable=False, index=True)
    ORDERSID = Column(ForeignKey(u'ORDERS.ORDERSID', ondelete=u'CASCADE'), nullable=False)
    ORDEREDITEMSQUANTITY = Column(Integer, nullable=False)

    ORDER = relationship(u'ORDER')

SQL 文件:

create table ORDERS
(
 ORDERSID             int not null auto_increment,     
 ORDERSCOST           decimal(19,4) not null,
 primary key (ORDERSID)
);

create table ORDEREDITEMS
(
 ORDEREDITEMSID       int not null auto_increment,
 ORDERSID             int not null,
 ITEMSID              int not null,
 ORDEREDITEMSQUANTITY int not null,
 primary key (ORDEREDITEMSID),
 unique key AK_ORDERSID_ITEMID (ORDERSID, ITEMSID)
);

alter table ORDEREDITEMS add constraint FK_ORDER_ORDEREDITEM foreign key (ORDERSID)
  references ORDERS (ORDERSID) on delete CASCADE on update restrict;

当我运行它时,我得到了错误:

 (IntegrityError) (1452, 'Cannot add or update a child row: a foreign key constraint fails (`my_database`.`ordereditems`,

 CONSTRAINT `FK_ORDER_ORDEREDITEM` FOREIGN KEY (`ORDERSID`) REFERENCES `ORDERS` (`ORDERSID`) ON DELETE CASCADE)') 

'UPDATE `ORDEREDITEMS` SET `ORDERSID`=%s WHERE `ORDEREDITEMS`.`ORDEREDITEMSID` = %s' (None, 3L)

当我直接在 phpMyAdmin 上执行相同的操作时,它按预期工作。

【问题讨论】:

    标签: python mysql sqlalchemy sql-delete


    【解决方案1】:

    一个完整的示例通常最有帮助,但我能够从您的示例中填充缺失的部分,并重现您的确切问题 - 尝试在删除后提交时尝试的 UPDATE 语句。 (完整的工作代码here,全是纯python,没有SQL语句。)

    这个问题之前被问过很多次了,我在this SO question中找到了答案。

    解决方法只是将 ORDEREDITEM 关系从

    ORDEREDITEM = relationship("ORDEREDITEM")
    

    ORDEREDITEM = relationship("ORDEREDITEM", cascade="all,delete")
    

    请参阅 sqlalchemy 文档here

    【讨论】:

    • 此外,由于 DB 外键约束具有 ON DELETE CASCADE,ORM 关系可以通过传递 passive_deletes=True 而不是 cascade="..., delete" 来删除 DB:docs.sqlalchemy.org/en/latest/orm/…
    【解决方案2】:

    外键关系涉及一个包含中心数据值的父表,以及一个具有相同值的子表指向其父表。 FOREIGN KEY 子句在子表中指定。

    如果父表中没有匹配的候选键值,它将拒绝任何尝试在子表中创建外键值的 INSERT 或 UPDATE 操作。

    SO Answers for Foreign Key ConstraintIntegrity Error

    更新

        create table ORDERS
        (
         ORDERSID             int not null auto_increment,     
         ORDERSCOST           decimal(19,4) not null,
         primary key (ORDERSID)
        );
    
        create table ORDEREDITEMS
        (
         ORDEREDITEMSID       int not null auto_increment,
         ORDERSID             int not null,
         ITEMSID              int not null,
         ORDEREDITEMSQUANTITY int not null,
         primary key (ORDEREDITEMSID),
         unique key AK_ORDERSID_ITEMID (ORDERSID, ITEMSID)
        );
    
        alter table ORDEREDITEMS add constraint FK_ORDER_ORDEREDITEM foreign key (ORDERSID)
          references ORDERS (ORDERSID) on delete CASCADE on update restrict;
          
        INSERT into ORDERS values(1,20.00);
        INSERT into ORDEREDITEMS values(1,1,1,2);
    

    现在,当您在 MySql 中运行上述命令时,您的数据已成功插入 Orders 和 ORDEREDITEMS DEMO1

    那么这个错误是什么时候产生的

    (IntegrityError) (1452, '无法添加或更新子行:外键约束失败

    当您的孩子(ORDEREDITEM)具有无效的父键时生成(即孩子包含无效的外键,该外键已从您的父表中删除或不存在)

    如果我尝试这样做

        INSERT into ORDEREDITEMS values(1,1,1,2);
        INSERT into ORDERS values(1,20.00);
    

    我得到错误,因为 OP 只是通过更改插入顺序得到的
    即使在删除时你也会遇到这个错误

        INSERT into ORDERS values(1,20.00);
    
        DELETE FROM ORDERS
        WHERE ORDERSID=1;
    
        INSERT into ORDEREDITEMS values(1,1,1,2);
    

    【讨论】:

    • 对不起,我不太明白你的回答。我正在尝试Delete 一行。在我的OrderedItems 表中,有orderID 对应于Order 表的行。
    • 基本上,在删除ORDER之前尝试删除属于ORDERORDEREDITEM行。
    • 感谢@StefanSchmidt。这是我最初所做的,但我认为使用 cascade 会是一个更简单的解决方案。
    • 你的错误与这一行有关吗'UPDATE ORDEREDITEMS` SET ORDERSID=%s WHERE ORDEREDITEMS.ORDEREDITEMSID = %s' (None, 3L)` 这是一个更新不是删除?这里的 null 值违反了您的约束。
    • 谢谢@gonkan。是的..我不确定它为什么要尝试update 条目,而不仅仅是delete 它。我认为它会找到所有 ordereditems 以及特定的 ordersIDdelete 它们。最后,它会删除带有idORDER
    猜你喜欢
    • 2011-06-29
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-16
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多