简体   繁体   中英

SQLAlchemy delete cascade fails

I am having trouble deleting a model instance from within SQLAlchemy. I recently added an additional table and this addition has introduced this problem. The table I added is called editrecords .

The database is MySQL with an InnoDB engine.

Models are defined below:

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

Here is the function where the delete occurs

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

I have tried modifying the ForeignKey property ondelete='CASCADE' on the models and rebuilding the database, although nothing is seeming to work. The editrecords table is giving me issues when I try to delete a test because it has a ForeignKey pointing to tests .

The error message I am getting is below (fired when I try to commit the transaction in 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)]

EDIT: result of SHOW CREATE TABLE <table> for the above tables

tests: http://pastebin.com/uFcEMzVZ

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

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

The issue is you have two foreign keys from foo tests and editrecord tables to test table

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

In this situation you cant have On delete cascade because lets assume if you delete record from editrecord then it will try to delete related record from test table (on Delete cascade) but those test ids are using as foreign keys in footest table as well due to that foregin key constrain it will not alow to delete those records from test table so your delete statement will fail

same thing happen if you going to delete it from foo test it has on delete cascade foreign key and it will try to delete records from test but they are already using as foreign keys in editrecord so it will not alowe to delete

this will be a dead look situation where you cant delete record from both table at same time. so please the issue is ON delete cascade and remove it from table level and handle it from code level

with this table design you cant delte entry from either footest or editrecord tables

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM