I know that you can insert multiple rows at once, is there a way to update multiple rows at once (as in, in one query) in MySQL?
Edit: For example I have the following
Name id Col1 Col2
Row1 1 6 1
Row2 2 2 3
Row3 3 9 5
Row4 4 16 8
I want to combine all the following Updates into one query
UPDATE table SET Col1 = 1 WHERE id = 1;
UPDATE table SET Col1 = 2 WHERE id = 2;
UPDATE table SET Col2 = 3 WHERE id = 3;
UPDATE table SET Col1 = 10 WHERE id = 4;
UPDATE table SET Col2 = 12 WHERE id = 4;
Yes, that's possible - you can use INSERT ... ON DUPLICATE KEY UPDATE.
Using your example:
Since you have dynamic values, you need to use an IF or CASE for the columns to be updated. It gets kinda ugly, but it should work.
Using your example, you could do it like:
The question is old, yet I'd like to extend the topic with another answer.
My point is, the easiest way to achieve it is just to wrap multiple queries with a transaction. The accepted answer
INSERT ... ON DUPLICATE KEY UPDATE
is a nice hack, but one should be aware of its drawbacks and limitations:"Field 'fieldname' doesn't have a default value"
MySQL warning even if you don't insert a single row at all. It will get you into trouble, if you decide to be strict and turn mysql warnings into runtime exceptions in your app.I made some performance tests for three of suggested variants, including the
INSERT ... ON DUPLICATE KEY UPDATE
variant, a variant with "case / when / then" clause and a naive approach with transaction. You may get the python code and results here. The overall conclusion is that the variant with case statement turns out to be twice as fast as two other variants, but it's quite hard to write correct and injection-safe code for it, so I personally stick to the simplest approach: using transactions.Edit: Findings of Dakusan prove that my performance estimations are not quite valid. Please see this answer for another, more elaborate research.
Not sure why another useful option is not yet mentioned:
All of the following applies to InnoDB.
I feel knowing the speeds of the 3 different methods is important.
There are 3 methods:
I just tested this, and the INSERT method was 6.7x faster for me than the TRANSACTION method. I tried on a set of both 3,000 and 30,000 rows.
The TRANSACTION method still has to run each individually query, which takes time, though it batches the results in memory, or something, while executing. The TRANSACTION method is also pretty expensive in both replication and query logs.
Even worse, the CASE method was 41.1x slower than the INSERT method w/ 30,000 records (6.1x slower than TRANSACTION). And 75x slower in MyISAM. INSERT and CASE methods broke even at ~1,000 records. Even at 100 records, the CASE method is BARELY faster.
So in general, I feel the INSERT method is both best and easiest to use. The queries are smaller and easier to read and only take up 1 query of action. This applies to both InnoDB and MyISAM.
Bonus stuff:
The solution for the INSERT non-default-field problem is to temporarily turn off the relevant SQL modes:
SET SESSION sql_mode=REPLACE(REPLACE(@@SESSION.sql_mode,"STRICT_TRANS_TABLES",""),"STRICT_ALL_TABLES","")
. Make sure to save thesql_mode
first if you plan on reverting it.As for other comments I've seen that say the auto_increment goes up using the INSERT method, I tested that too and it seems to not be the case.
Code to run the tests is as follows. It also outputs .SQL files to remove php interpreter overhead
This should work for ya.
There is a reference in the MySQL manual for multiple tables.
Use a temporary table
You can alias the same table to give you the id's you want to insert by (if you are doing a row-by-row update:
Additionally, It should seem obvious that you can also update from other tables as well. In this case, the update doubles as a "SELECT" statement, giving you the data from the table you are specifying. You are explicitly stating in your query the update values so, the second table is unaffected.
Why does no one mention multiple statements in one query?
In php, you use
multi_query
method of mysqli instance.From the php manual
Here is the result comparing to other 3 methods in update 30,000 raw. Code can be found here which is based on answer from @Dakusan
Transaction: 5.5194580554962
Insert: 0.20669293403625
Case: 16.474853992462
Multi: 0.0412278175354
As you can see, multiple statements query is more efficient than the highest answer.
If you get error message like this:
You may need to increase the
max_allowed_packet
in mysql config file which in my machine is/etc/mysql/my.cnf
and then restart mysqld.You may also be interested in using joins on updates, which is possible as well.
Edit: If the values you are updating aren't coming from somewhere else in the database, you'll need to issue multiple update queries.
There is a setting you can alter called 'multi statement' that disables MySQL's 'safety mechanism' implemented to prevent (more than one) injection command. Typical to MySQL's 'brilliant' implementation, it also prevents user from doing efficient queries.
Here (http://dev.mysql.com/doc/refman/5.1/en/mysql-set-server-option.html) is some info on the C implementation of the setting.
If you're using PHP, you can use mysqli to do multi statements (I think php has shipped with mysqli for a while now)
Hope that helps.
use
Please note:
The following will update all rows in one table
The next one will update all rows where the value of Column2 is more than 5
There is all Unkwntech's example of updating more than one table
Yes ..it is possible using INSERT ON DUPLICATE KEY UPDATE sql statement.. syntax: INSERT INTO table_name (a,b,c) VALUES (1,2,3),(4,5,6) ON DUPLICATE KEY UPDATE a=VALUES(a),b=VALUES(b),c=VALUES(c)
With PHP I did this. Use semicolon, split it into array and then submit via loop.
This should achieve what you'r looking for. Just add more id's. I have tested it.
// You just building it in php like
So you can update hole table with one query