108

I have two tables in MySQL

#messages table  : 
messageid
messagetitle 
.
.

#usersmessages table 
usersmessageid 
messageid
userid
.
.

Now if I want to delete from messages table it's ok. But when I delete message by messageid the record still exists on usersmessage and I have to delete from this two tables at once.

I used the following query :

DELETE FROM messages LEFT JOIN usersmessages USING(messageid) WHERE messageid='1' ; 

Then I test

   DELETE FROM messages , usersmessages 
   WHERE messages.messageid = usersmessages.messageid 
   and messageid='1' ; 

But these two queries are not accomplishing this task .

Luis Rico
  • 625
  • 6
  • 22
mehdi
  • 9,262
  • 11
  • 35
  • 35

11 Answers11

162

Can't you just separate them by a semicolon?

Delete from messages where messageid = '1';
Delete from usersmessages where messageid = '1'

OR

Just use INNER JOIN as below

DELETE messages , usersmessages  FROM messages  INNER JOIN usersmessages  
WHERE messages.messageid= usersmessages.messageid and messages.messageid = '1'
Jobin
  • 8,238
  • 1
  • 33
  • 52
Eric
  • 7,930
  • 17
  • 96
  • 128
  • 1
    what happen if i want to put this code in a loop ? i know i can put the semicolon absolutely . – mehdi Aug 05 '09 at 14:14
  • 1
    It can be put in a loop. You can do it programmtically and send the message id as a parameter. As long as you don't keep on sending it the same id it won't do the delete over and over. – Eric Aug 05 '09 at 14:17
  • @Eric Yeah , i Test This Query it working perfectly ;) tanks . but i do the same query before i post but it's dosen't work because i don't say messages.messageid='1' i just say messageid='1' ; tanks any way . – mehdi Aug 05 '09 at 14:25
  • @Eric i don't think it's good idea to create too queries to do simple task like this as long as i can do that in just one query . – mehdi Aug 05 '09 at 14:28
  • @Mehdi I hear you. But is the second query I gave you the one that worked? – Eric Aug 05 '09 at 14:29
  • @Eric Yes . this query is what i need . the second query is working for me . – mehdi Aug 05 '09 at 14:38
  • 5
    If you do this in two queries, you really should wrap this in a transaction. As for running delete queries in a loop, you are better off formulating a single query to do all the deletes. – JohnFx Aug 05 '09 at 14:43
  • 1
    Checkout another example of delete query with joins http://www.bennadel.com/blog/939-Using-A-SQL-JOIN-In-A-SQL-DELETE-Statement-Thanks-Pinal-Dave-.htm – Babar Aug 05 '09 at 15:02
  • 42
    Doesn't work with SQL Server: Incorrect syntax near ','. – Paul-Sebastian Manole Apr 06 '15 at 08:26
  • You must be doing something wrong. I have no problems in SQL Server with the above statements. Please note that if you're using the first syntax, it's a semi-colon and not a comma. – Eric Apr 06 '15 at 21:37
  • @Eric could this be altered to allow for a row to be deleted in one table even if there are no associated rows in the second table? – user2363025 Aug 06 '15 at 13:29
  • @user2363025 - Yup, you could use a `left join`, but make sure that your `where` clause is very limiting first!! Make sure you try this as a `select` before attempting the `delete`. The `left join` will pull back *all* rows on the left (first) table unless you limit it in the `left join`. – Eric Aug 07 '15 at 02:10
56
DELETE a.*, b.* 
FROM messages a 
LEFT JOIN usersmessages b 
ON b.messageid = a.messageid 
WHERE a.messageid = 1

translation: delete from table messages where messageid =1, if table uersmessages has messageid = messageid of table messages, delete that row of uersmessages table.

angry kiwi
  • 10,730
  • 26
  • 115
  • 161
  • comment for all: as shown in this exemple, it is important to specify in which table the delete should work . Great post @angry_kiwi – Raphael_b Apr 28 '15 at 09:54
  • I had just to change the order, FROM usersmessages b LEFT JOIN messages a – Pablo Jun 18 '15 at 12:10
19

You should either create a FOREIGN KEY with ON DELETE CASCADE:

ALTER TABLE usersmessages
ADD CONSTRAINT fk_usermessages_messageid
FOREIGN KEY (messageid)
REFERENCES messages (messageid)
ON DELETE CASCADE

, or do it using two queries in a transaction:

START TRANSACTION;;

DELETE
FROM    usermessages
WHERE   messageid = 1

DELETE
FROM    messages
WHERE   messageid = 1;

COMMIT;

Transaction affects only InnoDB tables, though.

Quassnoi
  • 413,100
  • 91
  • 616
  • 614
  • 3
    You *can* delete from multiple tables in one query! http://dev.mysql.com/doc/refman/5.0/en/delete.html – txwikinger Aug 05 '09 at 14:10
  • yes you can! But to me...it's easier to do what my answer said. – Eric Aug 05 '09 at 14:11
  • I added the cascade on a similar table of mine. When I attempted to delete from 1 table only, it deleted the record and left the related one orphaned. What good is the constraint? – barfoon Jun 22 '10 at 16:00
  • @barfoon: is your table `InnoDB`? – Quassnoi Jun 22 '10 at 16:02
  • @Quassnoi Oops! I definitely thought it was, what a goof. All tables are MyISAM. Can I change all of them on the fly with data in them? Or is there issues with that? – barfoon Jun 22 '10 at 17:01
  • @barfoon: yes you can but be aware that the `FULLTEXT` and `SPATIAL` indexes will not work in `InnoDB`. – Quassnoi Jun 23 '10 at 08:42
9

The OP is just missing the table aliases after the delete

DELETE t1, t2 
FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.id 
WHERE t1.id = some_id
goneos
  • 319
  • 2
  • 4
  • 16
8

You have two options:

First, do two statements inside a transaction:

BEGIN;
  DELETE FROM messages WHERE messageid = 1;
  DELETE FROM usermessages WHERE messageid = 1;
COMMIT;

Or, you could have ON DELETE CASCADE set up with a foreign key. This is the better approach.

CREATE TABLE parent (
  id INT NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE child (
  id INT, parent_id INT,
  FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE
);

You can read more about ON DELETE CASCADE here.

Mike Trpcic
  • 25,305
  • 8
  • 78
  • 114
8

no need for JOINS:

DELETE m, um FROM messages m, usersmessages um

WHERE m.messageid = 1 

AND m.messageid = um.messageid 
ekad
  • 14,436
  • 26
  • 44
  • 46
Fred Yates
  • 81
  • 1
  • 1
6
DELETE message.*, usersmessage.* from users, usersmessage WHERE message.messageid=usersmessage.messageid AND message.messageid='1'
Spudley
  • 166,037
  • 39
  • 233
  • 307
johan
  • 61
  • 1
  • 1
2

Try this please

DELETE FROM messages,usersmessages

USING messages

INNER JOIN usermessages on (messages.messageid = usersmessages.messageid)

WHERE messages.messsageid='1'
Prahalad Gaggar
  • 11,389
  • 16
  • 53
  • 71
Amit
  • 21
  • 2
1

Try this..

DELETE a.*, b.*  
FROM table1 as a, table2 as b  
WHERE a.id=[Your value here] and b.id=[Your value here]

I let id as a sample column.

Glad this helps. :)

Marian Nasry
  • 821
  • 9
  • 22
  • So that asterikses (`*`) are rendered properly you need to indent the query with 4 spaces in front of it. – Al.G. Oct 01 '17 at 10:26
0

You can also use like this, to delete particular value when both the columns having 2 or many of same column name.

DELETE project , create_test  FROM project INNER JOIN create_test
WHERE project.project_name='Trail' and  create_test.project_name ='Trail' and project.uid= create_test.uid = '1';
Vidya
  • 63
  • 2
  • 10
0

there's another way which is not mentioned here (I didn't fully test it's performance yet), you could set array for all tables -> rows you want to delete as below

// set your tables array
$array = ['table1', 'table2', 'table3'];


// loop through each table
for($i = 0; $i < count($array); $i++){

 // get each single array
 $single_array = $array[$i];

 // build your query
 $query = "DELETE FROM $single_array WHERE id = 'id'";

 // prepare the query and get the connection
 $data = con::GetCon()->prepare($query);

 // execute the action
 $data->execute();
}

then you could redirect the user to the home page.

header('LOCATION:' . $home_page);

hope this will help someone :)

Thanks

Midz Elwekil
  • 441
  • 4
  • 12
  • 1
    This might well help someone... looks like PHP though, I don't think that's necessarily within the scope of the question :) – Tom Bush Oct 08 '20 at 09:39