Updating instead of inserting if the row already exists - mysql

I'm facing an issue with SQL at the moment, i have got a relation between two columns in a table like this they are linked together as an unique key (id, charid) and using that relation i want to determine if i want to insert it or not, so if the following already exists
[charid: 1, id: 1]
I want to update it instead of inserting a new row, however if we insert a row like this and charid 1, id 1 already exists, that's OK and we can insert it.
[charid: 1, id: 1]
How can i correctly do this? I heard this could be done by using restrictions with the columns.

SQL Server:
UPDATE R
SET R.COLUMN = VALUE
FROM dbo.TABLE1 AS R
INNER JOIN dbo.TABLE2 AS P
ON R.charid = P.id
**Edit, actually you need a subquery with a "WHERE EXISTS" clause. Will update in a bit.
UPDATE R
SET R.COLUMN = VALUE
FROM dbo.TABLE1 AS R
WHERE EXISTS ( SELECT P.id
FROM dbo.TABLE2 AS P
WHERE R.charid = P.id )

It turns out, when you have a primary key or two, you can do the following instead:
(Please note: You do need atleast one primary key for this)
INSERT INTO arcade (id, charid, highscore) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE highscore = ?
this makes it so that when there's a duplicate key, it updates the row instead of trying to insert something!

Related

Conditional UPDATE MariaDB (MySQL)

Code:
UPDATE COMPANY SET id='21'
WHERE id='20';
Error:
SQLException: Duplicate entry '21' for key 'PRIMARY'
I want to UPDATE the primary key field in this case it's called 'id' to another value but if the value exists already it throws the error above. How would I do a conditional UPDATE based on if the 'id' doesn't exist in the COMPANY table already, to avoid throwing that error using MariaDB syntax.
NOTE:
I am NOT talking about doing a conditional INSERT that uses "ON DUPLICATE KEY UPDATE" as shown below.
INSERT INTO COMPANY(id,first,last,age)
VALUES('1','Tim','Jones','70')
ON DUPLICATE KEY UPDATE id='1';
You can use UPDATE IGNORE:
UPDATE IGNORE COMPANY
SET id='21'
WHERE id = '20'
See a simplified demo.
You can count the number of values already in the table:
UPDATE COMPANY C CROSS JOIN
(SELECT COUNT(*) as cnt
FROM COMPANY
WHERE id = 21
) CC
SET c.id = 21
WHERE id = 20 AND cnt = 0;
Note: In most databases, you would use NOT EXISTS in the WHERE clause, but MySQL/MariaDB doesn't support references to the table being updated.

MySQL: How To Add IF EXISTS Then UPDATE Else INSERT? [duplicate]

UPDATE AggregatedData SET datenum="734152.979166667",
Timestamp="2010-01-14 23:30:00.000" WHERE datenum="734152.979166667";
It works if the datenum exists, but I want to insert this data as a new row if the datenum does not exist.
UPDATE
the datenum is unique but that's not the primary key
Jai is correct that you should use INSERT ... ON DUPLICATE KEY UPDATE.
Note that you do not need to include datenum in the update clause since it's the unique key, so it should not change. You do need to include all of the other columns from your table. You can use the VALUES() function to make sure the proper values are used when updating the other columns.
Here is your update re-written using the proper INSERT ... ON DUPLICATE KEY UPDATE syntax for MySQL:
INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE
Timestamp=VALUES(Timestamp)
Try using this:
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that would cause a duplicate value in a UNIQUE index orPRIMARY KEY, MySQL performs an [UPDATE`](http://dev.mysql.com/doc/refman/5.7/en/update.html) of the old row...
The ON DUPLICATE KEY UPDATE clause can contain multiple column assignments, separated by commas.
With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values. If you specify the CLIENT_FOUND_ROWS flag to mysql_real_connect() when connecting to mysqld, the affected-rows value is 1 (not 0) if an existing row is set to its current values...
This is not too bad, but we could actually combine everything into one query. I found different solutions on the internet. The simplest, but MySQL only solution is this:
INSERT INTO wp_postmeta (post_id, meta_key)
SELECT
?id,
‘page_title’
FROM
DUAL
WHERE
NOT EXISTS (
SELECT
meta_id
FROM
wp_postmeta
WHERE
post_id = ?id
AND meta_key = ‘page_title’
);
UPDATE
wp_postmeta
SET
meta_value = ?page_title
WHERE
post_id = ?id
AND meta_key = ‘page_title’;
Link to documentation.
I had a situation where I needed to update or insert on a table according to two fields (both foreign keys) on which I couldn't set a UNIQUE constraint (so INSERT ... ON DUPLICATE KEY UPDATE won't work). Here's what I ended up using:
replace into last_recogs (id, hasher_id, hash_id, last_recog)
select l.* from
(select id, hasher_id, hash_id, [new_value] from last_recogs
where hasher_id in (select id from hashers where name=[hasher_name])
and hash_id in (select id from hashes where name=[hash_name])
union
select 0, m.id, h.id, [new_value]
from hashers m cross join hashes h
where m.name=[hasher_name]
and h.name=[hash_name]) l
limit 1;
This example is cribbed from one of my databases, with the input parameters (two names and a number) replaced with [hasher_name], [hash_name], and [new_value]. The nested SELECT...LIMIT 1 pulls the first of either the existing record or a new record (last_recogs.id is an autoincrement primary key) and uses that as the value input into the REPLACE INTO.

INSERT data from one table to another where ids match

I have two tables:
1. `blog_export`: 'id', 'body'.
'id' already has values 'body' is empty.
2. `field_data_body`: 'body_value','entity_id'
I would like to copy body_value from field_data_body and insert that data into the column 'body' on the table blog_export but ONLY where 'id' matches 'entity_id'
I have the statement
INSERT INTO `blog_export` (`body`)
SELECT `body_value`
FROM `field_data_body`
WHERE `bundle` = 'wp_blog' AND `entity_id` = `blog_export`.`id`
but it doesn't work. How do I do this?
You need to perform an UPDATE operation instead joining with other table like
UPDATE `blog_export` be
JOIN `field_data_body` fdb ON fdb.`entity_id` = be.`id`
SET be.`body` = fdb.`body_value`;
Depending on your current situation with your tables, you have at least these two options.
1) blog_export already has records for all the records with possible entity_id values in field_data_body. In this case, you just need to update all the records and you can simply use an update statement (instead of your insert), as others already recommended.
Either use the multiple-table syntax (just as in Rahul's answer):
UPDATE blog_export be
JOIN field_data_body fdb ON fdb.entity_id = be.id
SET be.body = fdb.body_value;
Or the single-table syntax:
UPDATE blog_export be
SET body = (SELECT body FROM field_data_body WHERE entity_id = be.id);
2) blog_export does not contain all the records with possible entity_id values in field_data_body (i.e. none of them, or maybe just a subset of them). In this case, you must insert new records to the table and update already existing ones.
You can use an insert statement with the ON DUPLICATE KEY UPDATE clause (supposing that blog_export.id is unique or primary key):
INSERT INTO blog_export (id, body)
SELECT entity_id, body_value
FROM field_data_body
ON DUPLICATE KEY UPDATE body=body_value;

insert into table only if not exist on other table

I'm trying to do the following thing:
I have two tables: ReportImage (imageId, reportId, counter)
and userReportedImages (imageId, userId)
I want that every user will be able to report an image only once - this means that first I want to check if there is a row in 'userReportedImages' with the values (imageId, userId) if so do nothing, else create a row in 'ReportImage' with the values (imageId, reportId, counter), if such row already exist (other user reported that image) then I want to raise the counter.
so far before checking for same user report I had the following statement:
INSERT INTO ReportImage VALUES (imageId,reportId,1) ON DUPLICATE KEY UPDATE counter = counter+1
this statement is working fine.
I tried to change this statement to first check if the row exist on the other table, but I didn't manage to do it, can you help me?
First, you need to define a UNIQUE constraint or a compund column primary key on table ReportImage,
ALTER TABLE ReportImage ADD CONTRAINT tb_uq UNIQUE(ImageID, ReportID)
Give this a try,
INSERT INTO ReportImage(ImageID, ReportID, Counter)
SELECT 'imageID HERE' AS ImageID,
'userID HERE' AS ReportID,
1 AS Counter
FROM userReportedImages a
LEFT JOIN ReportImage b
ON a.imageId = b.imageId AND
a.userId = b.ReportID AND
a.imageID = 'imageID HERE' AND
a.userID = 'userID HERE'
WHERE b.imageId IS NULL OR
b.ReportID IS NULL
ON DUPLICATE KEY UPDATE counter = VALUES(counter) + 1
you could try using NOT EXISTS
insert into table2(`name`)
select * from (select 'name1' as name) tmp
where not exists(
select ('x') from table1 where name = 'test1'
);
SQL Fiddle
An insert trigger should be a solution for you: link

MySql Table Insert if not exist otherwise update

UPDATE AggregatedData SET datenum="734152.979166667",
Timestamp="2010-01-14 23:30:00.000" WHERE datenum="734152.979166667";
It works if the datenum exists, but I want to insert this data as a new row if the datenum does not exist.
UPDATE
the datenum is unique but that's not the primary key
Jai is correct that you should use INSERT ... ON DUPLICATE KEY UPDATE.
Note that you do not need to include datenum in the update clause since it's the unique key, so it should not change. You do need to include all of the other columns from your table. You can use the VALUES() function to make sure the proper values are used when updating the other columns.
Here is your update re-written using the proper INSERT ... ON DUPLICATE KEY UPDATE syntax for MySQL:
INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE
Timestamp=VALUES(Timestamp)
Try using this:
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that would cause a duplicate value in a UNIQUE index orPRIMARY KEY, MySQL performs an [UPDATE`](http://dev.mysql.com/doc/refman/5.7/en/update.html) of the old row...
The ON DUPLICATE KEY UPDATE clause can contain multiple column assignments, separated by commas.
With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values. If you specify the CLIENT_FOUND_ROWS flag to mysql_real_connect() when connecting to mysqld, the affected-rows value is 1 (not 0) if an existing row is set to its current values...
This is not too bad, but we could actually combine everything into one query. I found different solutions on the internet. The simplest, but MySQL only solution is this:
INSERT INTO wp_postmeta (post_id, meta_key)
SELECT
?id,
‘page_title’
FROM
DUAL
WHERE
NOT EXISTS (
SELECT
meta_id
FROM
wp_postmeta
WHERE
post_id = ?id
AND meta_key = ‘page_title’
);
UPDATE
wp_postmeta
SET
meta_value = ?page_title
WHERE
post_id = ?id
AND meta_key = ‘page_title’;
Link to documentation.
I had a situation where I needed to update or insert on a table according to two fields (both foreign keys) on which I couldn't set a UNIQUE constraint (so INSERT ... ON DUPLICATE KEY UPDATE won't work). Here's what I ended up using:
replace into last_recogs (id, hasher_id, hash_id, last_recog)
select l.* from
(select id, hasher_id, hash_id, [new_value] from last_recogs
where hasher_id in (select id from hashers where name=[hasher_name])
and hash_id in (select id from hashes where name=[hash_name])
union
select 0, m.id, h.id, [new_value]
from hashers m cross join hashes h
where m.name=[hasher_name]
and h.name=[hash_name]) l
limit 1;
This example is cribbed from one of my databases, with the input parameters (two names and a number) replaced with [hasher_name], [hash_name], and [new_value]. The nested SELECT...LIMIT 1 pulls the first of either the existing record or a new record (last_recogs.id is an autoincrement primary key) and uses that as the value input into the REPLACE INTO.