Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cascading a delete to a many-to-many association table?

Tags:

sqlalchemy

I have a problem with cascading a delete. I have two tables, and they are mapped many-to-many:

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) 

This is the error I get:

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

Has anybody got an idea what I'm doing wrong?

I also asked the question on the sqlalchemy mailing list, and got the right answer:

You are telling SQLAlchemy to cascade File deletes to FileHost, but you want it the other way around. You can fix this by moving the cascade='all,delete-orphan' and single_parent=True clauses into the backref. You also probably want 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) 
}) 
like image 347
tom Avatar asked Jul 12 '10 21:07

tom


People also ask

What is a cascading delete?

A foreign key with cascade delete means that if a record in the parent table is deleted, then the corresponding records in the child table will automatically be deleted. This is called a cascade delete in SQL Server.

When to use cascading delete?

Use the ON DELETE CASCADE option to specify whether you want rows deleted in a child table when corresponding rows are deleted in the parent table. If you do not specify cascading deletes, the default behavior of the database server prevents you from deleting data in a table if other tables reference it.

Is Cascade delete good practice?

On delete cascade is a particularly bad thing to use to clean data because it doesn't discriminate against the data you want the FK to stop the delete for and the data you are trying to completely purge.

What is on delete cascade example?

ON DELETE CASCADE constraint is used in MySQL to delete the rows from the child table automatically, when the rows from the parent table are deleted. For example when a student registers in an online learning platform, then all the details of the student are recorded with their unique number/id.


1 Answers

It should be noted that while this wasn't the problem in this particular case, you may still get this error if you don't include ondelete="CASCADE" in the declaration of your foreign keys. Even after declaring cascade="all,delete" in my relationships, I was still getting this error until I added the ondelete attribute. You may want to add onupdate="CASCADE" as well.

like image 156
Chase Sandmann Avatar answered Oct 07 '22 10:10

Chase Sandmann