views:

90

answers:

4

I am trying to delete from a few tables at once. I've done a bit of research, and came up with this

DELETE FROM `pets` p,
            `pets_activities` pa
      WHERE p.`order` > :order
        AND p.`pet_id` = :pet_id
        AND pa.`id` = p.`pet_id`

However, I am getting this error

Uncaught Database_Exception [ 1064 ]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'p, pets_activities pa...

I've never done a cross table delete before, so I'm inexperienced and stuck for now!

What am I doing wrong?

Thanks

+2  A: 

You should not delete from multiple tables in one query.

DELETE FROM pets WHERE pet_id = :pet_id;
DELETE FROM pets_activities WHERE pet_id = :pet_id;

I'm not sure why you're deleting by pet_id and order. It seems strange to me, and I'd wonder what your reasoning is. If you wanted to delete by something else, you should do this:

DELETE FROM pets WHERE order > :order;
DELETE FROM pets_activities WHERE pet_id Not In (SELECT pet_id FROM pets);

And it's also ambiguous to name a column ID in the pets_activities table and expect anyone else to realize that it's supposed to be the pet_id from the pets table. You should name it pet_id instead for clarity.

Erick Robertson
Thanks. That may have been a typo. I changed the table names just to keep the client happy. I'll make an edit.
alex
Erick, you don't seem to be taking the `where order` clause into account in this one - it makes the second query a tad more complex.
paxdiablo
Not only the order, but also by the ID? This seems strange to me. If this was only being deleted based on the order, you could delete that, and then delete any records in the pets_activities where pet_id not In (SELECT pet_id FROM pets)
Erick Robertson
Erick, wouldn't this [documentation](http://dev.mysql.com/doc/refman/5.0/en/delete.html) confirm you *can* delete from multiple tables (at least with MySQL)?
alex
Just because you can doesn't mean you should. You'll notice I changed the wording of my answer slightly.
Erick Robertson
+1: This is the safest and most portable means of deleting records in a relationship, and I agree that syntax being unique/available justifies its use.
OMG Ponies
Keep in mind that this should be done inside a transaction since, as it stands, it's not atomic.
paxdiablo
It doesn't need to be atomic. The second statement is just a clean-up of unused data. The transaction would just be un-necessary overhead.
Erick Robertson
A: 

The syntax looks right to me ... try to change it to use INNER JOIN ...

Have a look at this: http://www.electrictoolbox.com/article/mysql/cross-table-delete/

afgallo
A: 

Since this appears to be a simple parent/child relationship between pets and pets_activities, you would be better off creating you foreign key constraint with a deleting cascade.

That way, when a pets row is deleted, the pets_activities rows associated with it are automatically deleted as well.

Then your query becomes a simple:

delete from `pets`
    where `order` > :order
      and `pet_id` = :pet_id
paxdiablo
Delete cascades are inviting horrible accidents.
Erick Robertson
Thanks Paxdiablo, I'm not sure how to do this yet in MySQL but I'll consider it.
alex
@Erick, provided you've set up referential integrity, cascading deletes can cause no more trouble than delete on its own. We already know that `pa` is a proper child of `p` due to the `id/pet_id` mapping.
paxdiablo
Cascading deletes just means that things will be deleted which you aren't explicitly saying to delete. That's always dangerous.
Erick Robertson
You _are_ explicitly saying you want to delete them. Just not at the time of delete. You don't explicitly say you want triggers fired at the time of insertion either but that doesn't make them dangerous.
paxdiablo
I disagree. I prefer to use a database as a database, and not as an execution platform.
Erick Robertson
I agree with Erick on this one - can be hazardous. Somewhat related, SQL Server 2005 doesn't handle cascade deletes if on the same table. The safest means is to process data in relational order
OMG Ponies
Well, you guys have your own thoughts but it seems like you're discounting a lot of the power of DBMS'. Cascading deletes are as much a part of data management as triggers, stored procedures or constraints and they're only dangerous if you don't know what you're doing. Still, I won't argue the point further, we'll just have to agree to disagree.
paxdiablo
Getting data in isn't the issue - it's situations where you have to reconstruct data that wasn't supposed to be deleted which is a real hassle. Only Oracle has Flashback, a temporal compliment to it's database for inline reconstituting accidentally deleted data. SQL Server has snapshots, but it's nowhere near as slick as Flashback. That's why Erick, myself, and numerous others I've worked with prefer explicit deletion. Like the case with SQL Server, it's not always a cut'n'dried operation either, or hasn't been in the past.
OMG Ponies
Again, not an issue if it's set up correctly - the problems you mention are no different to deleting rows accidentally _without_ cascade. Seriously, if someone doesn't know how to design and implement databases, they have no business trying to do it.
paxdiablo
It probably comes as no surprise, but I also do not use triggers, stored procedures, or constraints. I prefer to put this kind of logic in my execution platform and use my database for storing and retrieving data only. This doesn't mean I don't know how to use or understand these features, however.
Erick Robertson
Erick, now you've piqued my interest. How do you ensure data integrity within the database without constraints?
paxdiablo
+1  A: 

I don't have a mysql database to test on at the moment, but have you tried specifying what to delete prior to the from clause? For example:

DELETE p, pa FROM `pets` p,
        `pets_activities` pa
  WHERE p.`order` > :order
    AND p.`pet_id` = :pet_id
    AND pa.`id` = p.`pet_id`

I think the syntax you used is limited to newer versions of mysql.

Brandon Horsley
That query executed successfully, however, it didn't delete any rows (but I believe it should have).
alex