mysql update with ON DUPLICATE KEY UPDATE - mysql

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

Related

Delete entry that is connected to 2 tables

table 1 is called (athlete) and table2 is called (training_session.id) the primary key to table 1 is ID, and the table 2 has the primary key Athelete_id
I want to delete a person from my database by using his name, which I've called "Pet". However, he is also connected to another table which stores his training session. So (ID 1) on table 1 is connected to table 2 (athlete id1)
I struggle a lot, I try using INNER JOIN.
DELETE athlete,training_session FROM athlete
INNER JOIN
training_session ON training_session.id = athlete.name
WHERE
athlete.name = "Pet;
I have something wrong with my syntax, is it correct to use Inner Join or have I misunderstood
You should have set up foreign key constraints with Cascade deletions to simplify the logic and all you would have needed than was to delete from athlete. So I would suggest you add it.
For more info you can take a look at:
http://www.mysqltutorial.org/mysql-on-delete-cascade/

select then delete mysql query

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)

SQL DELETE with INNER JOIN

There are 2 tables, spawnlist and npc, and I need to delete data from spawnlsit.
npc_templateid = n.idTemplate is the only thing that "connect" the tables.
I have tried this script but it doesn't work.
I have tried this:
DELETE s FROM spawnlist s
INNER JOIN npc n ON s.npc_templateid = n.idTemplate
WHERE (n.type = "monster");
Add .* to s in your first line.
Try:
DELETE s.* FROM spawnlist s
INNER JOIN npc n ON s.npc_templateid = n.idTemplate
WHERE (n.type = "monster");
If the database is InnoDB then it might be a better idea to use foreign keys and cascade on delete, this would do what you want and also result in no redundant data being stored.
For this example however I don't think you need the first s:
DELETE s
FROM spawnlist AS s
INNER JOIN npc AS n ON s.npc_templateid = n.idTemplate
WHERE n.type = "monster";
It might be a better idea to select the rows before deleting so you are sure your deleting what you wish to:
SELECT * FROM spawnlist
INNER JOIN npc ON spawnlist.npc_templateid = npc.idTemplate
WHERE npc.type = "monster";
You can also check the MySQL delete syntax here: http://dev.mysql.com/doc/refman/5.0/en/delete.html
if the database is InnoDB you dont need to do joins in deletion. only
DELETE FROM spawnlist WHERE spawnlist.type = "monster";
can be used to delete the all the records that linked with foreign keys in other tables, to do that you have to first linked your tables in design time.
CREATE TABLE IF NOT EXIST spawnlist (
npc_templateid VARCHAR(20) NOT NULL PRIMARY KEY
)ENGINE=InnoDB;
CREATE TABLE IF NOT EXIST npc (
idTemplate VARCHAR(20) NOT NULL,
FOREIGN KEY (idTemplate) REFERENCES spawnlist(npc_templateid) ON DELETE CASCADE
)ENGINE=InnoDB;
if you uses MyISAM you can delete records joining like this
DELETE a,b
FROM `spawnlist` a
JOIN `npc` b
ON a.`npc_templateid` = b.`idTemplate`
WHERE a.`type` = 'monster';
in first line i have initialized the two temp tables for delet the record,
in second line i have assigned the existance table to both a and b but here i have linked both tables together with join keyword,
and i have matched the primary and foreign key for both tables that make link,
in last line i have filtered the record by field to delete.

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

How to insert a row, but on duplicate; update it instead?

I have a table which contains the items the users of my game owns. If a user buys a new item, it should be inserted, but if he already got it, it should be increased instead.
I understand I can use INSERT ... ON DUPLICATE KEY UPDATE, but I don't understand how in my problem.
The item_id isn't unique, because many players can own the same weapon (ie. a longsword). The user_id isn't unique either, because a player can own many items.
So, my question is how to make the query UPDATE instead of INSERT if a row containing both the user_id and item_id already exists?
I know this question is old but none of the answers are correct.
You need a PRIMARY or UNIQUE index on user_id and item_id (both columns in one index).
Then you can use "INSERT INTO ... VALUES ... ON DUPLICATE KEY UPDATE count=count+1" no problem.
This is EXACTLY what ON DUPLICATE UPDATE will do for you.
That's not what the "ON DUPLICATE KEY UPDATE" will do for you. If it were me, I would attempt the insert. If it failed, check why (you're checking for errors already, right?). If it's because of a duplicate key, do your update. If the error is for some other reason, then handle that appropriately.
You do want ON DUPLICATE KEY UPDATE. It looks for the Primary Key of the table, and if it exists, updates all the other rows.
So your table has a primary key of (userid, itemid) and the following values:
userid itemid strength
4 5 6
And you want to bump it to strength=9, use this:
INSERT INTO table ON DUPLICATE KEY UPDATE VALUES(4,5,9)
It will insert a row with 4,5,9 if it doesn't exist, and will update strength to 9 on the row with primary key (4,5) if it does exist. It won't update any other rows (e.g. rows with userid4 but itemid 10 or itemid 5 but userid 70) because they don't match the whole PK.
You could do something like the following (assumes your user id is in the variable UserID and item ID is in item_ID) :
SELECT
#rowCount := COUNT(*)
FROM
table
WHERE
user_id = UserID
AND item_id = ItemID;
IF (#rowCount > 0) THEN
... do update
ELSE
... do insert
END IF;
Can you do something like
UPDATE TABLE
set COL = 'BLAH BLAH'
where ITEM_ID = #itemid AND USER_ID = #userid
IF ##ROWCOUNT = 0
BEGIN
INSERT INTO TABLE (col...)
VALUES (vals...
END