Which of those operations should perform faster in MySQL? Presume I have 999 values to change:
DELETE FROM table WHERE id IN(100, ..., 999);
INSERT INTO example VALUES (100, 'Peter'), (...), (999, 'Sam');
OR
UPDATE table_name SET name='Peter'
WHERE person_id=100; ...; UPDATE table_name SET name='Sam' WHERE person_id=999;
Since you have only 900 row values to change then first option will perform fast. Because you will have only two queries to run. But if you go for second option then you will have almost 900 queries to run that will definitely slow. And more better idea to do same would be
TRUNCATE FROM table;
INSERT INTO example VALUES (100, 'Peter'), (...), (999, 'Sam');
because truncate works faster than delete.
In the general case, those two operations (DELETE/INSERT vs UPDATE) could have significantly different results, based on the current state of the table... Does row with id=999 exist? Are there foreign key constraints that reference this table? Are there any triggers defined on the table?
If the specification is to update rows in a table, I would issue an UPDATE statement, rather than issuing a DELETE and INSERT.
There are factors beyond speed to consider.
But fastest would likely be:
UPDATE example t
SET t.name
= CASE t.id
WHEN 100 THEN 'Peter'
WHEN ...
WHEN 999 THEN 'Sam'
ELSE t.name
END
WHERE t.id IN (100,...999)
Related
The below sql query i require to run an update instead of an insert due to duplicates.
Insert into test_reports (Table_Name, Total_Count) SELECT "West Midlands", COUNT(1) FROM table1 where location = 'West Midlands'
Thanks
A good way to deal with this problem is to differentiate between when there's no previous record and when there is a previous record. For that, you can use the ON DUPLICATE KEY phrase of an INSERT:
INSERT INTO **INSERT-PHRASE** ON DUPLICATE KEY **UPDATE-PHRASE**
Use REPLACE INTO instead.
More here: http://dev.mysql.com/doc/refman/5.0/en/replace.html
Note though that it deletes before it inserts, so any fields not in the query will be set to their defaults. If you do not want that behaviour, use UPDATE.
I think I am having some problems related to concurrent inserts so I wanted to know if such concurrent insert statements -
insert into table1 (field1,field2,field3) Values (A,B,C);
insert into table1 (field1,field2,field3) Values (1,2,3);
could result in a row like
A B 3
A and B from the first insert statement and the 3 from the second insert statement. My table is using InnoDB storage btw.
The answer is no. Inserts and updates normally lock the tables/row they are operating on so that won't happen.
Is it possible to perform update like insert?
UPDATE `table` SET `value` ('N','N','N','N','Y','Y','Y','N', 'N') WHERE `my_id` = '1'
The problem is that the number of values to be inserted i dont now. It can be a 5 or 10.
replace is just like insert, it just checks if there is duplicate key and if it is it deletes the row, and inserts the new one, otherwise it just inserts
you can do this if there is for example unique index of (Name,Type) and if you type the following command
REPLACE INTO table1 (Name,Type,InitialValue,FinalValue) VALUES ('A',3,50,90 )
and there already exists a row with Name = 'A' and Type = 3 it will be replaced
CREATE UNIQUE INDEX idx_name_type ON table1(Name,Type)
EDIT: a quick note - REPLACE always DELETES and then INSERTs, so it is never a very good idea to use it in heavy load because it needs exclusive lock when it deletes, and then when it inserts
some of the database engines have
INSERT ... ON DUPLICATE KEY UPDATE ...
You have to specify the column-name.
UPDATE `table` SET `Col1`='y',`Col2`='n' ... WHERE `ID`='1'
Or want to update one or more columns/rows:
UPDATE `table` Set Col1='Y' WHERE `ID` IN ('1','11','13')
I want to do all these update in one statement.
update table set ts=ts_1 where id=1
update table set ts=ts_2 where id=2
...
update table set ts=ts_n where id=n
Is it?
Use this:
UPDATE `table` SET `ts`=CONCAT('ts_', `id`);
Yes you can but that would require a table (if only virtual/temporary), where you's store the id + ts value pairs, and then run an UPDATE with the FROM syntax.
Assuming tmpList is a table with an id and a ts_value column, filled with the pairs of id value, ts value you wish to apply.
UPDATE table, tmpList
SET table.ts = tmpList.ts_value
WHERE table.id = tmpList.id
-- AND table.id IN (1, 2, 3, .. n)
-- above "AND" is only needed if somehow you wish to limit it, i.e
-- if tmpTbl has more idsthan you wish to update
A possibly table-less (but similar) approach would involve a CASE statement, as in:
UPDATE table
SET ts = CASE id
WHEN 1 THEN 'ts_1'
WHEN 2 THEN 'ts_2'
-- ..
WHEN n THEN 'ts_n'
END
WHERE id in (1, 2, ... n) -- here this is necessary I believe
Well, without knowing what data, I'm not sure whether the answer is yes or no.
It certainly is possible to update multiple rows at once:
update table table1 set field1='value' where field2='bar'
This will update every row in table2 whose field2 value is 'bar'.
update table1 set field1='value' where field2 in (1, 2, 3, 4)
This will update every row in the table whose field2 value is 1, 2, 3 or 4.
update table1 set field1='value' where field2 > 5
This will update every row in the table whose field2 value is greater than 5.
update table1 set field1=concat('value', id)
This will update every row in the table, setting the field1 value to 'value' plus the value of that row's id field.
You could do it with a case statement, but it wouldn't be pretty:
UPDATE table
SET ts = CASE id WHEN 1 THEN ts_1 WHEN 2 THEN ts_2 ... WHEN n THEN ts_n END
I think that you should expand the context of the problem. Why do you want/need all the updates to be done in one statement? What benefit does that give you? Perhaps there's another way to get that benefit.
Presumably you are interacting with sql via some code, so certainly you can simply make sure that the three updates all happen atomically by creating a function that performs all three of the updates.
e.g. pseudocode:
function update_all_three(val){
// all the updates in one function
}
The difference between a single function update and some kind of update that performs multiple updates at once is probably not a very useful distinction.
generate the statements:
select concat('update table set ts = ts_', id, ' where id = ', id, '; ')
from table
or generate the case conditions, then connect it to your update statement:
select concat('when ', id, ' then ts_', id) from table
You can use INSERT ... ON DUPLICATE KEY UPDATE. See this quesion: Multiple Updates in MySQL
ts_1, ts_2, ts_3, etc. are different fields on the same table? There's no way to do that with a single statement.
In MySQL, if you specify ON DUPLICATE KEY UPDATE and a row is inserted that would cause a duplicate value in a UNIQUE index or PRIMARY KEY, an UPDATE of the old row is performed. For example, if column a is declared as UNIQUE and contains the value 1, the following two statements have identical effect:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
I don't believe I've come across anything of the like in T-SQL. Does SQL Server offer anything comparable to MySQL's ON DUPLICATE KEY UPDATE?
I was surprised that none of the answers on this page contained an example of an actual query, so here you go:
A more complex example of inserting data and then handling duplicate
MERGE
INTO MyBigDB.dbo.METER_DATA WITH (HOLDLOCK) AS target
USING (SELECT
77748 AS rtu_id
,'12B096876' AS meter_id
,56112 AS meter_reading
,'20150602 00:20:11' AS time_local) AS source
(rtu_id, meter_id, meter_reading, time_local)
ON (target.rtu_id = source.rtu_id
AND target.time_local = source.time_local)
WHEN MATCHED
THEN UPDATE
SET meter_id = '12B096876'
,meter_reading = 56112
WHEN NOT MATCHED
THEN INSERT (rtu_id, meter_id, meter_reading, time_local)
VALUES (77748, '12B096876', 56112, '20150602 00:20:11');
There's no DUPLICATE KEY UPDATE equivalent, but MERGE and WHEN MATCHED might work for you
Inserting, Updating, and Deleting Data by Using MERGE
You can try the other way around. It does the same thing more or less.
UPDATE tablename
SET field1 = 'Test1',
field2 = 'Test2'
WHERE id = 1
IF ##ROWCOUNT = 0
INSERT INTO tablename
(id,
field1,
field2)
VALUES (1,
'Test1',
'Test2')
SQL Server 2008 has this feature, as part of TSQL.
See documentation on MERGE statement here - http://msdn.microsoft.com/en-us/library/bb510625.aspx
SQL server 2000 onwards has a concept of instead of triggers, which can accomplish the wanted functionality - although there will be a nasty trigger hiding behind the scenes.
Check the section "Insert or update?"
http://msdn.microsoft.com/en-us/library/aa224818(SQL.80).aspx