select then delete mysql query - mysql

I have a users table and it is possible for one or more users to become related. I have a column in the database called referred and if it has an ID in it, if that ID gets deleted from the database, then the associated users must go too.
Here is my query:
START TRANSACTION;
DELETE FROM users
WHERE id IN
( SELECT a.id
FROM users a
JOIN users b ON a.referred = b.id );
If I remove user Josh Murray with id='1', anyone that matches criteria referred='1' must be deleted also.

I would suggest to create table with foreign keys with specifying action ON DELETE for example:
ALTER TABLE users
ADD CONSTRAINT FK_REFERRED
FOREIGN KEY (referred)
REFERENCES users(id)
ON DELETE CASCADE
So that if for example user with ID = 4 was referencing to user with ID = 1 and another user with ID = 7 is referencing to the first user(ID = 4), when user with ID = 1 is deleted, user with ID = 4 will be also deleted, and user with ID = 7 will be deleted too.
So you wouldn't bother with deleting all other 'children' nodes of the data

will this not do ?
Delete from users where (id = 1 or referred = 1)

Related

How to do a "DELETE" relational database with another table in MySQL

I want to have a relational data between two table with DELETE query.
I don't know what keyword should I search and such confusing for me to learn relational database.
So in this case, I want to delete one of the user data in the user table.
So the buy_product table which contains the user_id column will also be deleted along with the rows in it.
This is user table:
user_id
name
1
John
2
Doe
This is buy_product table:
id_product
name
user_id
1
Cookies
2
2
Pizza
2
3
Burger
1
For example, if I run the DELETE FROM user WHERE user_id = 2 query, the result is:
user_id
name
1
John
And buy_product table with user_id = 2 also deleted the data that I want without run DELETE FROM buy_product WHERE user_id = 2 query like this:
id_product
name
user_id
3
Burger
1
I think for all understandable answers means a lot to me. Thanks!
If you defined a foreign key constraint with ON DELETE CASCADE between buy_product and user then deleting a row from the parent table user will automatically delete the related rows in the child table buy_product.
For example, buy_product could be created as:
create table buy_product (
id_product int,
name varchar(50),
user_id int references user (user_id) on delete cascade
);
Ideally you should configure cascading deletion such that when a record is deleted from the user table all dependent records are also deleted from the buy_product table. In lieu of that, we can try doing a delete join here:
DELETE u, bp
FROM user u
INNER JOIN buy_product bp
ON bp.user_id = u.user_id
WHERE u.user_id = 2;

MySQL: unique data for 2 fields

It is not so simple as it is written in the title.
I have a table, for binding user accounts together.
For example: a person signs up via standard site functionality. On the next day he signs up via the Facebook account.
I have user_user table with a_user_id, b_user_id fields. These fields are foreign keys to the standard user table.
I make unique key for 2 fields.
But. How to avoid the situation like this one:
a_user_id: 1
b_user_id : 2
and the next row:
a_user_id: 2
b_user_id : 1
Both rows mean the same. Can MySQL handle this?
Are there any better approaches for this case?
Introduce the constraint a_user_id < b_user_id. Honestly said, I till now always held this constraint on the programming side, This prevents cycles: self references and a-b-a.
First one would need to normalize the table, probably using a temporary table in MySQL.
Normalisation of the old table:
Assuming a table u2(a_user_id NOT NULL, b_user_id NOT NULL):
DELETE FROM u2
WHERE a_user_id = b_user_id;
ALTER TABLE u2 ADD COLUMN other ...;
UPDATE u2
SET
other = a_user_id,
a_user_id = b_user_id,
b_user_id = other
WHERE
a_user_id > b_user_id;
ALTER TABLE u2 REMOVE COLUMN other;
(Unchecked syntax)

MySQL delete FROM multiple tables where key can be found in different columns in the same table

I have multiple tables holding infos about users and content.
Table users:
id name
5 foo
33 abc
Table imgs:
id uid img_name
1 5 bar
8 33 xy
Table user_permissions:
id uid permission_id
1 5 3
2 3 3
Table liked_content:
id contente_id content_holder_id likedby_id
1 8 33 5
2 1 5 56
If a user is deleted I want to delete all rows in all tables related to his user-id. This works fine if I add only one column per table.
DELETE users,
imgs,
user-permissions,
liked_content
FROM users,
imgs,
user-permissions,
liked_content
WHERE imgs.uid = users.id AND
user_permissions.uid = users.id AND
liked_content.content_holder_id = users.id AND
users.id = 5
Adding a second row in the WHERE-clause (likedby_id/liked_content-table) where the id can be found will not work.
...
WHERE imgs.uid = users.id AND
user_permissions.uid = users.id AND
liked_content.content_holder_id = users.id AND
liked_content.likedby_id = users.id AND
users.id = 5
What would be the correct way adding a second column to the query for a table already listed?
According to your data, user id can be in liked_content table as either content_holder_id OR likedby_id. Not necessarily as both. Where clause should change as:
...
WHERE imgs.uid = users.id AND
user_permissions.uid = users.id AND
(liked_content.content_holder_id = users.id OR
liked_content.likedby_id = users.id) AND
users.id = 5
If you use foreign key constraint along with cascade delete rule, you do not have to do this manually.
What you're implementing yourself is a cascading delete. It is generally built into the DB engine. Check out this related question: MySQL foreign key constraints, cascade delete
If you were dead set on doing it yourself, I'd recommend multiple delete statements within a transaction that traverse your schema from child to parent:
DELETE
FROM liked_content
WHERE content_holder_id = 5;
DELETE
FROM imgs
WHERE uid = 5;
DELETE
FROM user-permissions
WHERE uid = 5;
DELETE
FROM users
WHERE id = 5;
The technically correct way, as others have stated, is to setup cascading deletes.
I would not willingly do that if I was in charge of the database, simply because you will find it to be very painful trying to manipulate the tables and especially when you are trying to create sample data.
I would go for the KISS method...
Do a DELETE for each subordinate table individually referring to the users id, then delete the master record.
If you do the foreign key and cascading thing, you will not like what it does to your content table, since it has two relations to the master user table.
It means, for example, if you are attempting to delete content rows for holder_id 5, you will first have to disconnect those rows from their associated likedby_id master record by setting the likedby_id to NULL, otherwise the cascade would delete the likedby_id master record. But, it also won't allow you to NULL the likedby_id because doing so would invalidate the foreign key relations you need to actually do the cascade.
Do yourself a favor - Go simple.

mysql update with ON DUPLICATE KEY UPDATE

I have a table of foreign key and I am trying to merge duplicate records.
My table looks like this:
user_id | object_id
The table is a two column unique key, so there cannot be duplicates.
My query looks like this:
UPDATE user_object SET object_id = merge_obj_id WHERE object_id = old_object_id
This works fine until there is a user attached to both the old object and the merged_object. Which causes a duplicate. I'm stuck, I can think of ways to do this with multiple queries and object manipulation but I would really like to do this in SQL.
UPDATE:
This might work?
INSERT INTO user_object (user_id,merge_object_id) SELECT user_id FROM user JOIN
user_object ON user.user_id = user_object.user_id WHERE object_id = old_object_id ON
DUPLICATE KEY (DELETE user_object WHERE user_object.user_id = user_id AND
user_object.user_id = old_object_id);`
UPDATE:
Tried this:
INSERT user_object(user_id,object_id)
SELECT 12345 as object_id, user.user_id as user_id
FROM user
JOIN user_object ON user.user_id = user_object.user_id
WHERE user_object.object_id = 23456
But it give me this error:
Cannot add or update a child row: a foreign key constraint fails (yourtable.user_object, CONSTRAINT FK_user_object_user_idx FOREIGN KEY (user_id) REFERENCES user (user_id))
You could use
REPLACE INTO user_object(user_id,object_id) SELECT 12345 as object_id, user.user_id as user_id FROM user JOIN user_object ON user.user_id = user_object.user_id
WHERE user_object.object_id = 23456
This will delete any old rows which match before inserting the new row.
When you merge two objects do you maintain both the old object and the merged one or do you remove one of them? If you delete the new object which was merged into the old one then there is no need to update the primary keys as the old object reference is still valid
I think you want
INSERT .... ON DUPLICATE KEY UPDATE"
http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

Is this a valid MySQL query?

I've got 4 tables: users, messages, files, notes. I want to make a query which will delete all of a users' stuff if he's deleted. Will the following work:
DELETE FROM users, messages, files, notes WHERE userId = '$userId'
All 4 tables have got the column userId
You can split the statements in to four separate statements, in order to delete the rows associated with the userid.
DELETE FROM users WHERE userId = '$userId'
DELETE FROM messages WHERE userId = '$userId'
DELETE FROM files WHERE userId = '$userId'
DELETE FROM notes WHERE userId = '$userId'
The other alternative would be to cascade the deletes across the foreign keys.
When you create a foreign key you can choose what you want to do to the child records on the deletion of a parent record. This is denoted below by specifying the ON Delete in the creation of the foreign key. Here is some reference http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
DELETE u, m, f, p
FROM users u
LEFT JOIN
messages m
ON m.user_id = u.id
LEFT JOIN
files f
ON f.user_id = u.id
LEFT JOIN
posts p
ON p.user_id = u.id
WHERE u.id = 1
This assumes that the record with id = 1 exists in users, otherwise nothing will be deleted.
Note, however, that this is not very efficient and four separate deletes will work better.
in the where statement, if you have more than one table reference, you should refer to TABLE.COLUMN,
eg : WHERE users.userid = '$userId'.
I recommend to do 1 sentence per table
In your WHERE, you have userId = '$userId'. Other people can correct me if I'm wrong, but I'm pretty sure that the userId would be ambiguous and this statement wouldn't run. #John Hartsocks answer should work though if that is indeed the case.
That is besides the point though. If you're worried about making sure a user is completely deleted, then you should be using foreign key constraints. You said when you delete a user, you want to make sure that all information pertaining to that user is deleted. If you add the FK constraint to every table that has a user id (besides the users table, in which case it would have the primary key constraint), it should not be possible for you to delete a user, without first making sure all other data referencing that user is deleted.
Yes.
http://dev.mysql.com/doc/refman/5.0/en/delete.html