I have table with AUTO_INCREMENT field defined as PRIMARY_KEY.
I have columns like:
vote_id,vote_user_id,vote_ask_id,vote_comment_id,vote_post_id,vote_type,vote_status
I want to INSERT new records but before I do that I want to check if there is a row with columns(vote_user_id,vote_ask_id,vote_type) as same as the new data I want INSERT.
CONDITIONS:
IF ROW EXISTS
THEN UPDATE tableName SET vote_status=new_value, vote_time=new_time
ELSE
INSERT NEW RECORDS
I have searched the internet and learnt about MySQL ..ON DUPLICATE KEY UPDATE.
I have realize this statement will not be helpful to my task since it only checks for DUPLICATE KEY(...PRIMARY_KEY or UNIQUE FIELD).
I have learnt also on MySQL REPLACE INTO ...and likewise this will not be helpful to my problem since that is also bind to PRIMARY_KEY or UNIQUE index.
I learnt I could use MERGE....USING...statements
but this was giving me errors so i read more about it and I relised it only work in SQL server (Microsoft)
Please how best can someone help me solve this?
I tried this on MERGE staments:
MERGE {$votes_table} WITH (HOLDLOCK) AS VT
USING ({$Qid},{$vote_type},{$CUid},{$vote_status}) AS VTS (vote_ask_id,vote_type,vote_user_id,vote_status)
ON( VT.vote_ask_id = VTS.vote_ask_id AND VT.vote_user_id=VTS.vote_user_id AND VT.vote_type=VTS.vote_type)
WHEN MATCHED THEN
UPDATE SET VT.status=VST.vote_status , VT.vote_time='{$current_time}' WHERE VT.vote_user_id=VTS.vote_user_id AND VT.vote_ask_id=VTS.vote_ask_id AND VT.vote_type=VTS.vote_type
WHEN NOT MATCHED THEN INSERT (vote_ask_id,vote_type,vote_status,vote_user_id,vote_time) VALUES('{$Qid}','{$vote_type}','{$vote_up_status}','{$CUid}','{$current_time}')
In MySQL, use ON DUPLICATE KEY:
INSERT INTO tablename (vote_user_id, vote_ask_id, vote_type, . . . )
VALUES (new_vote_user_id, new_vote_ask_id, new_vote_type . . . )
ON DUPLICATE KEY UPDATE vote_status = VALUES(vote_status), vote_time = VALUES(vote_time);
For this to work, you need a unique index/constraint on the columns that define a unique row:
CREATE UNIQUE INDEX unq_tablename_3 ON tablename(vote_user_id, vote_ask_id, vote_type);
You do want insert ... on duplicate key update: in MySQL, this is the right way to do what you want.
To start with, you need to create a unique constraint on the tuple of concerned columns:
create unique index votes_table_unique_idx
on votes_table(vote_user_id, vote_ask_id, vote_type);
Then, you can do something like:
insert into votes_table(vote_user_id, vote_ask_id, vote_type, vote_comment_id, vote_post_id, vote_status)
values(...)
on duplicate key update
vote_comment_id = values(vote_comment_id),
vote_post_id = values(vote_post_id)
vote_status = values(vote_status)
Related
I have a quick question about MySQL behavior.
Imagine a table with 3(relevant) columns:
id (PK + AI),somedate,someuser,etc...
I have put a unique constraint on (date,user). So when I start with a clean test table and run the following query twice:
REPLACE INTO `testtable` (somedate,someuser) VALUES('2017-01-01','admin');
I expected a row with the 'id' column on 1. but instead everytime I run this query the id goes up because of the auto increment and I can't have that happen (this would corrupt my data relations). Why is this? Can I make it so that I can keep the original primary key when a replace into occurs?
Not with the REPLACE. That's like an INSERT preceded by a DELETE. The behavior you observe with REPLACE is the same as the behavior you would see if you executed these two statements:
DELETE FROM `testtable` WHERE somedate = '2017-01-01' and someuser = 'admin';
INSERT INTO `testtable` (somedate,someuser) VALUES ('2017-01-01','admin');
And that means the auto_increment column on the newly inserted row will have a new value.
Perhaps consider using INSERT ... ON DUPLICATE KEY UPDATE.
Reference: https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
(Note that the attempt to insert a row that gets updated will use an auto_increment value.)
To me looks like you actually wanted an UPDATE statement rather like
update `testtable`
set somedate = '2017-01-01',
someuser = 'admin'
where id = <id of the record> ;
If the record doesn't exist , i need to insert a new record , but if it exists then
i need to select a particular column value from that row and do an update based on it .
I have managed to write down below query , which does insert / Update using duplicate on update
insert into securities(symbol, buyerquan, sellerquan , totaltradedquan) values('BANKBARODA', 73, 0, 4290270) on duplicate key update buyerquan=buyerquan+VALUES(buyerquan),sellerquan=sellerquan+VALUES(sellerquan),totaltradedquan=totaltradedquan+VALUES(totaltradedquan)
This is my sqlfiddle http://sqlfiddle.com/#!2/aaf91/5
My requirement is
If the record exists , how can i fetch the existing column , compare it and then do an update ??
Do we need to write an another SQL query for fetching existing column value ??
If record exists fetch the existing column , compare it and then do an update Or else just insert new record
Can we do all this in same query ??
Can anybody please help me .
Mysql has a shortcut for that, it's called "INSERT ... ON DUPLICATE KEY UPDATE"
http://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html
Your question is vague. For instance, you don't specify what columns are used to define a duplicate. Based on your query, I am guessing that you mean symbol.
Your query is:
insert into securities(symbol, buyerquan, sellerquan , totaltradedquan)
values('BANKBARODA', 73, 0, 4290270)
on duplicate key update buyerquan = buyerquan+VALUES(buyerquan),
sellerquan = sellerquan + VALUES(sellerquan),
totaltradedquan = totaltradedquan + VALUES(totaltradedquan);
This seems to be the right syntax (which for most people that is the hard part of the question). The only thing that is missing is the specification of uniqueness:
create unique index securities_symbol on securities(symbol);
You can also specify this condition in the create table statement, using the unique keyword.
Is there a way of removing record on duplicate key in MySQL?
Say we have a record in the database with the specific primary key and we try to add another one with the same key - ON DUPLICATE KEY UPDATE would simply update the record, but is there an option to remove record if already exists? It is for simple in/out functionality on click of a button.
It's a work-around, but it works:
Create a new column and call it do_delete, or whatever, making it a tiny-int. Then do On Duplicate Key Update do_delete = 1;
Depending on your MySQL version/connection, you can execute multiple queries in the same statement. However, if not, just run a separate query immediately afterwords. Either way, the next query would just be: Delete From [table] Where do_delete = 1;. This way, if its a new entry, it will not delete anything. If it was not a new entry, it will then mark it for deletion then you can delete it.
Use REPLACE INTO:
replace into some_table
select somecolumn from othertable
will either insert new data or if thr same data exist will delete the data and insert the new one
The nearest possible solution for the same is REPLACE statement. Here is the documentation for REPLACE.
A similar question was asked on MySQL Forums and the recommended(and only) answer was to use REPLACE.
to be more clear with mySql:
values can be from same table:
replace into table1 (column1,column2) select (val1,val2) from table1
or
values can be from another table:
replace into table1 (column1,column2) select (val1,val2) from table2
or
values can be from any table with condition:
replace into table1 (column1,column2) select (val1,val2) from table1 where <br>column3=val3 and column4=val4 ...
or
also remember values can be static with table name for namesake:
replace into table1 (column1,column2) select (123,"xyz") from table1
no error will be thrown even if the update results in duplicate entry, as it will be replaced.
(remember) only autoincrement value will be increased;
and
if you have column with data-type "TIMESTAMP" with "on update CURRENT_TIMESTAMP", it will have no effect;
Yes of course there is a solutions in MySQL for your problem.
If you want to delete or skip the new inserting record if there already a duplicate record exists in the key column of the table, you can use IGNORE like this:
insert ignore into mytbl(id,name) values(6,'ron'),(7,'son');
Here id column is primary key in the table mytbl. This will insert multiple values in the table by deleting or skipping the new duplicate records.
Hope this will fulfill your requirement.
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.
I know that you can use ON DUPLICATE KEY UPDATE to update a certain value if there is a record for that key already,
I can do this:
INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1, 2, 3)
ON DUPLICATE KEY UPDATE `a`=1, `b`=2, `c`=3
But how can I do this without having to write out the columns and values twice?
Unfortunately not.
You can get half-way there by not having to repeat the value:
INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);
But you still have to list the columns.
use REPLACE INTO
The meaning of REPLACE INTO is that IF the new record presents new key values, then it will be inserted as anew record.
IF the new record has key values that match a pre-existing record,then the key violation will be ignored and the new record will replace the pre-existing record.
If it is useful, I made a query to avoid writing by hand the last part of the "on duplicate" query, for versions >= 5.0:
SELECT GROUP_CONCAT( CONCAT(COLUMN_NAME,"=values(", COLUMN_NAME,")") SEPARATOR ", ") FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'database_name' AND TABLE_NAME = 'table_name';
and its output is this:
a=values(a), b=values(b), c=values(c), d=values(d)
on a table that has columns a,b,c and d, so you can append to the first part of the query:
INSERT INTO `tableName` (`a`,`b`,`c`, `d`) VALUES (1,2,3,4) ON DUPLICATE KEY UPDATE a=values(a), b=values(b), c=values(c), d=values(d)
UPDATE:
For a very long list of columns you may see a truncated output, you may use this statement before the query above (thanks Uncle iroh):
SET SESSION group_concat_max_len = 1000000;
per #BhendiGawaar's comment on #Lightness Races in Orbit's answer, here is the MySQL 8.019+ version:
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new
ON DUPLICATE KEY UPDATE c = new.a+new.b;
OR
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new(m,n,p)
ON DUPLICATE KEY UPDATE c = m+n;
Works with set as well:
INSERT INTO t1 SET a=1,b=2,c=3 AS new
ON DUPLICATE KEY UPDATE c = new.a+new.b;
INSERT INTO t1 SET a=1,b=2,c=3 AS new(m,n,p)
ON DUPLICATE KEY UPDATE c = m+n;
Copied directly from MySQL Docs
The deprecation warning about the use of VALUES:
The use of VALUES() to refer to the new row and columns is deprecated beginning with MySQL 8.0.20, and is subject to removal in a future version of MySQL. Instead, use row and column aliases, as described in the next few paragraphs of this section.
i know this is an old question, and this is a somewhat unconventional answer, but i ran into the same thing and was having issues with setting the group_concat_max_len property mentioned in another answer and was always getting a truncated result. Another option that I ultimately went with when writing a long script was to use this formula in excel:
=SUBSTITUTE(TRIM(A1), ",", "") & " = VALUES(" & SUBSTITUTE(TRIM(A1), ",", "") & "),"
where A1 is the cell you copy the field name into. To do this quickly, I'd right click the table and copy the select statement to the clipboard, which gives you all the colum names, the formula removes the commas.
Hope this helps someone!