SQLAlchemy 删除级联完整性错误

SQLAlchemy Delete Cascade Integrity Error

我正在尝试从我的数据库中 delete 一个 order,同时删除与之相关的所有 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 上执行相同的操作时,它按预期工作。

Foreign key relationships involve a parent table that holds the central data values, and a child table with identical values pointing back to its parent. The FOREIGN KEY clause is specified in the child table.

It will reject any INSERT or UPDATE operation that attempts to create a foreign key value in a child table if there is no a matching candidate key value in the parent table.

SO Answers for Foreign Key Constraint 或者 Integrity 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 中 运行 以上命令时,您的数据已成功插入订单和 ORDEREDITEMS DEMO1

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

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

它是在您的 child (ORDEREDITEM) 具有 Parent 的无效键时生成的(即 child 包含无效的外键,该外键已从您的 [=39 中删除或不存在=] table)

如果我尝试这样做

    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);

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

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

修复只是将 ORDEREDITEM 关系从

更改为
ORDEREDITEM = relationship("ORDEREDITEM")

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

请参阅 sqlalchemy 文档 here