INSERT IGNORE - How can I tell if inserted? - mysql

I am going to need an SQL query that would INSERT .. ON DUPLICATE KEY UPDATE (or INSERT IGNORE INTO) my table.
I need to know if an update actually took place or rather a new row was inserted.
A good reference was this SO answer, unfortunately there's no answer to the action taken.
As for now I am using INSERT .. ON DUPLICATE KEY UPDATE:
INSERT INTO `tbl` (`CLIENT_ID`, `COMP_ID`, `DATETIME`) VALUES (12334,32,NOW())
ON DUPLICATE KEY UPDATE
`COMP_ID`=VALUES(`COMP_ID`), `DATETIME`=VALUES(`DATETIME`);";
and check the affected_rows value.
If affected_rows equals 1, means -> new row inserted
If affected_rows equals 2, means -> row updated
I'd like no change to happen in case of a duplicate, but I would like to know a duplicate exists.
Using MYSQL

Inspect the number of rows affected:
A return value of 1 means an INSERT occurred
A return value of 2 means an UPDATE occurred
If you're using JDBC, this is the int return value of the update() or execute() call.
All frameworks have a way of passing this value back to you, for example Hibernate's Query.executeUpdate() returns this int value.

Related

MySQL replace into and get last insert ID

In MySQL, will a REPLACE INTO query work with the LAST_INSERT_ID function?
Essentially, I have to insert into one table, only where it doesn't exist, but then either way insert into the second table with a foreign key constraint of the first table.
So ie.
REPLACE INTO TABLE1(NAME) VALUES('unique');
SET #table1_id = LAST_INSERT_ID();
INSERT INTO TABLE2(TABLE1_ID, VALUE) VALUES(#table1_id, 'Test Value');
Will that function as intended on both an insert and an update?
Yes, REPLACE INTO query affects the result of LAST_INSERT_ID() function.
Documentation states:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.
That means if INSERT affects LAST_INSERT_ID() then REPLACE should do it too.
I have tested it with MySQL 8.

INSERT ... ON DUPLICATE KEY UPDATE how can I tell which records updated and which inserted

In a PHP script I'm using the MySQL INSERT ... ON DUPLICATE KEY UPDATE command to insert/update a number of records in my DB.
Is there anything that MySQL returns to say which records were inserted or updated?
An 'ugly' way would be to do a SELECT before each INSERT and see if the key exists before each INSERT but I'd like to know if MySQL has this function built in.
In case anyone need further info on what I'm trying to do is, to save the record id's to a log.
You will need another SELECT regardless, specifically SELECT ROW_COUNT().
From http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_row-count
For INSERT ... ON DUPLICATE KEY UPDATE statements, the affected-rows value is 1 if the row is inserted as a new row and 2 if an existing row is updated.
No, there is no way to tell which records were inserted and which were updated purely with the means provided by MySQL without additional queries. However, you can add a column to the table where you can keep an indicator that you can use to mark the record as updated instead of inserted, e.g.
INSERT INTO YourTable (Col1, Col2, Updated)
VALUES ("value1", "value2", 0)
ON DUPLICATE KEY UPDATE
Col1 = values(Col1),
Col2 = values(Col2),
Updated = 1

INSERT if PRIMARY KEY is not present, IGNORE if present [duplicate]

This is what I'm doing right now (name is UNIQUE):
SELECT * FROM fruits WHERE name='apple';
Check if the query returned any
result. If yes, don't do anything. If
no, a new value has to be inserted:
INSERT INTO fruits (name) VALUES ('apple');
Instead of the above is it ok to insert the value into the table without checking if it already exists? If the name already exists in the table, an error will be thrown and if it doesn't, a new record will be inserted.
Right now I am having to insert 500 records in a for loop, which results in 1000 queries. Will it be ok to skip the "already-exists" check?
You can use the IGNORE feature:
INSERT IGNORE INTO fruits VALUES ('apple')
If there is a key violation, it just skips this value
check out
INSERT IGNORE INTO ...
and
INSERT ON DUPLICATE KEY UPDATE ...
Thes second method is preferred as the IGNORE statement simply causes mysql to issue warning instead of error

UPON DUPLICATE KEY increment multiple columns?

Im running a database log and every day I log on a new row. My Mysql query therefore checks if the day (date (the unique key)) already exists, and if so, it tries to increment all the loggable values of the log-row by one. If the date record doesnt eyist yet, it will create a new row.
My SQL query is:
INSERT INTO `log` (`date`,`hits`,`stale`)
VALUES ('2012-03-06',1,1)
ON DUPLICATE KEY
UPDATE `hits`=`hits`+1,`stale`=`stale`+1
WHERE `date`='2012-03-06';"
All columns have 0 as default value, so if this query runs directly after midnight only 'stale' and 'hits' are set to 1. Otherwise 'stale' and 'hits' are both incremented.
I wish! (it doesn't work).
What am I missing? Which separator other then a comma should I use between 'hits' = 'hits' +1 and 'stale'='stale'+1?
Just get rid of the WHERE clause:
INSERT INTO `log` (`date`,`hits`,`stale`)
VALUES ('2012-03-06',1,1)
ON DUPLICATE KEY
UPDATE `hits`=`hits`+1,`stale`=`stale`+1;
Your separator is correct, but the UPDATE has already found the duplicate row to be able to trigger the ON DUPLICATE KEY, so you don't need to try to select it again using WHERE.
INSERT INTO `log` (`date`,`hits`,`stale`)
VALUES ('2012-03-06',1,1)
ON DUPLICATE KEY
UPDATE `hits`=`hits`+1,`stale`=`stale`+1
Demo here.
You shouldn't have the WHERE clause. ON DUPLICATE KEY UPDATE automatically limits the row it affects to the one that has the existing key.
Remove it and your query should work fine.
If you only want to do the update if some specific expression is true, you can do it with two statements:
INSERT IGNORE INTO x VALUES (.....);
UPDATE x SET ..... WHERE .....;
The INSERT will silently fail if there is a duplicate key.

INSERT INTO query only if record doesn't already exist

In my table I have two fields: v_id and ip_address. I want to insert some data into this table only if the IP address doesn't already exist.
After Google'ing I came across the INSERT IGNORE INTO statement, and this is my code:
public function update_visits($ip_address)
{
$sql = 'INSERT IGNORE INTO `24h_visits` (ip_address) VALUES (?)';
if($this->db->query($sql, array($ip_address)))
{
return TRUE;
}
return FALSE;
}
It runs fine and without errors, but duplicate rows are still being made, even if the same IP is passed in as a parameter.
Anyone got a clue? Thanks.
You have to create a UNIQUE index on ip_address for INSERT IGNORE to work:
ALTER TABLE 24h_visits
ADD UNIQUE INDEX(ip_address)
However, I haven't seen the entirety of your schema, but I would assume that there's a column that stores a timestamp of the last visit. It's the only way this would make sense (so you can purge visits older than 24 hours every now and then).
In this case, you actually don't want INSERT IGNORE, but INSERT ... ON DUPLICATE KEY UPDATE instead. Assuming you have a column called last_visit:
INSERT INTO 24h_visits (ip_address, last_visit)
VALUES ('$ip_address', NOW())
ON DUPLICATE KEY UPDATE last_visit = NOW();
With INSERT IGNORE, the new row is never inserted, and thus you would always have the first value ever inserted on last_visit, which (the way I see it) is not entirely correct.
Add the UNIQUE constraint to your ip_address column.
Then your query would fail if it attempts to add a duplicate ip_address row (unless you use INSERT IGNORE).
The other answers don't actually answer the question: Creating a unique index prevents the duplicate from being inserted, which is a good idea, but it doesn't answer "how to insert if not already there".
This is how you do it:
INSERT IGNORE INTO 24h_visits (ip_address)
select ?
where not exists (select * from 24h_visits where ip_address = ?)
Additionally, this approach does not require any changes to schema.