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;
Related
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)
Basically, I have two table users and user_details. Users table is as follows.
id name
1 A
2 B
and user details table is as follows
id user_id division branch
1 1 D1 B1
2 1 D2 B2
User_details table have user_id as the foreign key.
I need to import data from these two table into another database having similar two tables.
The problem is tables in db2 might already have entries with similar primary keys of user table. i.e. same user_id's.
Is there any way , I can change primary keys while maintaining the foreign key relation with user details table.
e.g. If db2 has user ids till 100, user id from db 1 should become 101 and this should also change the corresponding user id in user details table to 101 and so on.
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.
I am trying to create a to do web app using mysql. Can someone explain how I can select the todos specific for one user? How do I link the users table with the todos table? General advice would be preffered, not actual code.
It is called a foreign key relation. It goes like this
users table
-----------
id (auto increment primary key)
name
address
...
todos table
-----------
id (auto increment primary key)
user_id (id from users table - this is the foreign key and relation to the user)
todo_text
...
If you want to select the todos of a user later then you can use a join:
select todos.*
from todos
inner join users on users.id = todos.user_id
where users.name = 'john'
You would link them by id's
So if you have two tables (UserTable) and (ToDoTable) you would get the todos with a select like this.
Select * from ToDoTable where ToDoTable.user_id = 1;
That query is essentially saying give me everything from the todotable where the user is bob (since bob has a primary key id of 1)
The user table will have users like :
Name | id
Bob 1
John 2
and the TodoTable will have
Task | user_id
Clean dishes 2
Take out Trash 1
That way we link the tasks to the user table by the user_id
The User table will have a primary key (id)
and it is referenced on the todo table as a foreign key
I have a table contains columns like:
time tv_program user_name
xxx friends John
xxx Game of Thrones Kate
...
...
Now I want to create separate index table for tv_program and user_name like:
id tv_program
1 friends
2 Game of Thrones
3 ...
4 ...
id user_name
1 John
2 Kate
3 ...
4 ...
and update the original table, replace the tv_program and user_name with the index number instead like
time tv_program user_name
xxx 1 1
xxx 2 2
... ... ...
Is there any simple way to do this? many thanks!!
You basically want to normalise your data, and you can do it with MySQL queries:
Create a table tv_programs table with id autoincrement, name index unique
INSERT INTO tv_programs (name) SELECT DISTINCT tv_program
FROM original_table
Now you have a table containing the programs, with their id automatically created by MySQL, so you now have to run an UPDATE with join (using string names, could be slow if you have lots of data and no index, but you just run it once) and update the original table with the id of the joined table (tv_programs)
UPDATE original_table ot LEFT JOIN tv_programs tp ON ot.tv_program = tp.name SET ot.tv_program = tp.id
And now you can change the type of tv_program column to INT
Repeat with the other table. Do backups before, or add a column to the original table (e.g. tv_program_id) and update that one with IDs, so that you can run other queries to check the results before dropping the old column and continue
Hope that's clear.