SQLAlchemy删除级联失败

时间:2016-06-28 17:28:28

标签: python mysql sqlalchemy innodb

我在SQLAlchemy中删除模型实例时遇到问题。我最近添加了一个额外的表,这个添加引入了这个问题。我添加的表名为editrecords

数据库是带有InnoDB引擎的MySQL。

模型定义如下:

from sqlalchemy.ext.declarative import declarative_base
Model = declarative_base(name='Model')

class HasId(object):
    @declared_attr
    def id(cls):
        return Column('id', Integer, Sequence('test_id_seq'), primary_key=True)
    ...

class TestParent(HasId, Model):
    __tablename__ = 'tests'
    discriminator = Column(String(50))
    __mapper_args__ = {'polymorphic_on': discriminator}
    ...

class FooTest(TestParent):
    __tablename__ = 'footests'
    __mapper_args__ = {'polymorphic_identity': 'footests'}
    id = Column(Integer, ForeignKey('tests.id', ondelete='CASCADE'), primary_key=True)
    ...

class EditRecord(Model):
    __tablename__ = 'editrecords'
    id = Column(Integer, Sequence('editrecord_id_seq'), primary_key=True)
    test_id = Column(Integer, ForeignKey('tests.id', ondelete='CASCADE'), nullable=False)
    ...

这是删除发生的功能

def delete_test(test_id):
    test = TestParent.query.get(test_id)
    db_session.delete(test)
    db_session.commit()
    return( jsonify( {'deleted_test': test_id} ) )

我尝试修改模型上的ForeignKey属性ondelete='CASCADE'并重建数据库,尽管似乎没有任何工作。我尝试删除测试时,editrecords表格给了我一些问题,因为它有ForeignKey指向tests

我收到的错误消息如下(当我尝试在delete_test中提交交易时触发)

IntegrityError: (pymysql.err.IntegrityError) (1452, u'Cannot add or update a child row: a foreign key constraint fails (`bayswater_DEV`.`editrecords`, CONSTRAINT `editrecords_ibfk_1` FOREIGN KEY (`test_id`) REFERENCES `tests` (`id`) ON DELETE CASCADE)') [SQL: u'UPDATE editrecords SET test_id=%s WHERE editrecords.id = %s'] [parameters: (None, 2)]

编辑:上表SHOW CREATE TABLE <table>的结果

测试:http://pastebin.com/uFcEMzVZ

footests:http://pastebin.com/62uhECYn

editrecords:http://pastebin.com/3LekPywN

1 个答案:

答案 0 :(得分:0)

问题是你有两个来自foo测试和editrecord表的外键到测试表

footests

CONSTRAINT `footests_ibfk_1` FOREIGN KEY (`id`) REFERENCES `tests` (`id`) ON DELETE CASCADE,
  CONSTRAINT `footests_ibfk_2` FOREIGN KEY (`parent_id`) REFERENCES `footests` (`id`) ON DELETE CASCADE;

edotrecords

CONSTRAINT `editrecords_ibfk_1` FOREIGN KEY (`test_id`) REFERENCES `tests` (`id`) ON DELETE CASCADE,
  CONSTRAINT `editrecords_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`);

在这种情况下你不能删除级联 因为我们假设您从 editrecord 删除记录 它将尝试从测试表中删除相关记录(在删除级联上) 但是那些测试ID也在 footest 表中用作外键 由于foregin键约束,它不会从测试表中删除那些记录,因此你的delete语句将失败

同样的事情发生,如果你要从foo测试删除它有删除级联外键,它会尝试从测试中删除记录,但他们已经在editrecord中使用外键,所以它不会删除

这将是一个看不见的情况,你不能同时从两个表中删除记录。所以请问题是ON删除级联并从表级别删除它并从代码级别处理它

使用此表设计,您无法从footest或editrecord表中删除条目