197

I have table - config. Schema: config_name | config_value

And I would like to update multiple records in one query. I try like that:

UPDATE config 
SET t1.config_value = 'value'
  , t2.config_value = 'value2' 
WHERE t1.config_name = 'name1' 
  AND t2.config_name = 'name2';

but that query is wrong :(

Can you help me?

icedwater
  • 4,701
  • 3
  • 35
  • 50
user3022527
  • 2,107
  • 2
  • 14
  • 11

17 Answers17

227

Try either multi-table update syntax

UPDATE config t1 JOIN config t2
    ON t1.config_name = 'name1' AND t2.config_name = 'name2'
   SET t1.config_value = 'value',
       t2.config_value = 'value2';

Here is a SQLFiddle demo

or conditional update

UPDATE config
   SET config_value = CASE config_name 
                      WHEN 'name1' THEN 'value' 
                      WHEN 'name2' THEN 'value2' 
                      ELSE config_value
                      END
 WHERE config_name IN('name1', 'name2');

Here is a SQLFiddle demo

mtlynch
  • 3,403
  • 4
  • 31
  • 31
peterm
  • 91,357
  • 15
  • 148
  • 157
196

You can accomplish it with INSERT as below:

INSERT INTO mytable (id, a, b, c)
VALUES (1, 'a1', 'b1', 'c1'),
(2, 'a2', 'b2', 'c2'),
(3, 'a3', 'b3', 'c3'),
(4, 'a4', 'b4', 'c4'),
(5, 'a5', 'b5', 'c5'),
(6, 'a6', 'b6', 'c6')
ON DUPLICATE KEY UPDATE id=VALUES(id),
a=VALUES(a),
b=VALUES(b),
c=VALUES(c);

This insert new values into table, but if primary key is duplicated (already inserted into table) that values you specify would be updated and same record would not be inserted second time.

mandza
  • 330
  • 9
  • 24
camille khalaghi
  • 2,149
  • 1
  • 12
  • 6
  • 38
    a pretty smart hack. I am amazed. – Blaise Mar 04 '16 at 21:22
  • 8
    Not supported for Postgres see: http://stackoverflow.com/questions/1109061/insert-on-duplicate-update-in-postgresql – kevzettler Nov 23 '16 at 19:04
  • 2
    Also, it's a great way to turn a little bit of CSV (or a lot) into a table insert/update/upsert with some minor text editing! – wulftone Dec 08 '16 at 05:23
  • hmm, tried to use this with stored procedure + table valued parameter, but I'm getting `Incorrect syntax near the keyword 'ON'` error... do you perhaps know a way how to mass-update using stored procedures and table value parameter? – Prokurors Jan 28 '17 at 21:42
  • 11
    This is a MySQL solution, not Postgres or MSSQL. – Rz Mk Dec 23 '17 at 15:30
  • 9
    This will increment the autoincrement id, even if the record isn't inserted or updated – Timo Huovinen Jul 05 '19 at 19:51
  • Similar is possible for Postgres, using `EXCLUCED.id` - see one of below answers for details – maicher Aug 04 '19 at 12:41
  • This will fail, if we have column `d` that doesn't have a default value and is not nullable. – Danon Feb 02 '23 at 00:12
33

in my case I have to update the records which are more than 1000, for this instead of hitting the update query each time I preferred this,

   UPDATE mst_users 
   SET base_id = CASE user_id 
   WHEN 78 THEN 999 
   WHEN 77 THEN 88 
   ELSE base_id END WHERE user_id IN(78, 77)

78,77 are the user Ids and for those user id I need to update the base_id 999 and 88 respectively.This works for me.

vaibhav kulkarni
  • 1,733
  • 14
  • 20
32

instead of this

UPDATE staff SET salary = 1200 WHERE name = 'Bob';
UPDATE staff SET salary = 1200 WHERE name = 'Jane';
UPDATE staff SET salary = 1200 WHERE name = 'Frank';
UPDATE staff SET salary = 1200 WHERE name = 'Susan';
UPDATE staff SET salary = 1200 WHERE name = 'John';

you can use

UPDATE staff SET salary = 1200 WHERE name IN ('Bob', 'Frank', 'John');
Shuhad zaman
  • 3,156
  • 32
  • 32
11

maybe for someone it will be useful

for Postgresql 9.5 works as a charm

INSERT INTO tabelname(id, col2, col3, col4)
VALUES
    (1, 1, 1, 'text for col4'),
    (DEFAULT,1,4,'another text for col4')
ON CONFLICT (id) DO UPDATE SET
    col2 = EXCLUDED.col2,
    col3 = EXCLUDED.col3,
    col4 = EXCLUDED.col4

this SQL updates existing record and inserts if new one (2 in 1)

Oleh Sobchuk
  • 3,612
  • 2
  • 25
  • 41
  • 2
    As i can see, id is pk for the table as per your query.Suppose there are 2 or more columns considered as pk(Composite key)...In that case what should be the correct way to check the conflict. – Sritam Jagadev Sep 13 '17 at 10:24
9

Camille's solution worked. Turned it into a basic PHP function, which writes up the SQL statement. Hope this helps someone else.

    function _bulk_sql_update_query($table, $array)
    {
        /*
         * Example:
        INSERT INTO mytable (id, a, b, c)
        VALUES (1, 'a1', 'b1', 'c1'),
        (2, 'a2', 'b2', 'c2'),
        (3, 'a3', 'b3', 'c3'),
        (4, 'a4', 'b4', 'c4'),
        (5, 'a5', 'b5', 'c5'),
        (6, 'a6', 'b6', 'c6')
        ON DUPLICATE KEY UPDATE id=VALUES(id),
        a=VALUES(a),
        b=VALUES(b),
        c=VALUES(c);
    */
        $sql = "";

        $columns = array_keys($array[0]);
        $columns_as_string = implode(', ', $columns);

        $sql .= "
      INSERT INTO $table
      (" . $columns_as_string . ")
      VALUES ";

        $len = count($array);
        foreach ($array as $index => $values) {
            $sql .= '("';
            $sql .= implode('", "', $array[$index]) . "\"";
            $sql .= ')';
            $sql .= ($index == $len - 1) ? "" : ", \n";
        }

        $sql .= "\nON DUPLICATE KEY UPDATE \n";

        $len = count($columns);
        foreach ($columns as $index => $column) {

            $sql .= "$column=VALUES($column)";
            $sql .= ($index == $len - 1) ? "" : ", \n";
        }

        $sql .= ";";

        return $sql;
    }
adamk
  • 370
  • 4
  • 13
6

Execute the code below to update n number of rows, where Parent ID is the id you want to get the data from and Child ids are the ids u need to be updated so it's just u need to add the parent id and child ids to update all the rows u need using a small script.

 UPDATE [Table]
 SET column1 = (SELECT column1 FROM Table WHERE IDColumn = [PArent ID]),
     column2 = (SELECT column2 FROM Table WHERE IDColumn = [PArent ID]),
     column3 = (SELECT column3 FROM Table WHERE IDColumn = [PArent ID]),
     column4 = (SELECT column4 FROM Table WHERE IDColumn = [PArent ID]),
 WHERE IDColumn IN ([List of child Ids])
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Harrish Selvarajah
  • 1,763
  • 12
  • 11
5

Execute the below code if you want to update all record in all columns:

update config set column1='value',column2='value'...columnN='value';

and if you want to update all columns of a particular row then execute below code:

update config set column1='value',column2='value'...columnN='value' where column1='value'
Jason Clark
  • 1,307
  • 6
  • 26
  • 51
  • 5
    what if different value in different row? for example UPDATE staff SET salary = 1125 WHERE name = 'Bob'; UPDATE staff SET salary = 1200 WHERE name = 'Jane'; UPDATE staff SET salary = 1100 WHERE name = 'Frank'; UPDATE staff SET salary = 1175 WHERE name = 'Susan'; UPDATE staff SET salary = 1150 WHERE name = 'John'; – Abdullah Nurum Feb 13 '19 at 17:27
4

Assuming you have the list of values to update in an Excel spreadsheet with config_value in column A1 and config_name in B1 you can easily write up the query there using an Excel formula like

=CONCAT("UPDATE config SET config_value = ","'",A1,"'", " WHERE config_name = ","'",B1,"'")

Ivar
  • 41
  • 1
3
INSERT INTO tablename
    (name, salary)
    VALUES 
        ('Bob', 1125),
        ('Jane', 1200),
        ('Frank', 1100),
        ('Susan', 1175),
        ('John', 1150)
        ON DUPLICATE KEY UPDATE salary = VALUES(salary);
janw
  • 8,758
  • 11
  • 40
  • 62
jay10
  • 51
  • 1
  • 2
    Hi, the question asks for a way to update multiple rows whereas the code you shared is for inserting multiple rows. – Utsav Barnwal Nov 19 '20 at 17:17
  • 2
    this is the best solution in my opinion – zhouji Dec 29 '20 at 22:26
  • 1
    @UtsavBarnwal This is an INSERT command, but for rows where there is a match on PRIMARY or UNIQUE keys (in this case 'name') then MYSQL will do an UPDATE command. With VALUES() used to take the value from the INSERT data or 'salary' would be updated with the column data already in the db. – tristanbailey Feb 01 '21 at 12:00
  • @tristanbailey thanks for the explanation. I just tried it with a complex query, it worked perfectly. Kudos to jay10 – Utsav Barnwal Feb 01 '21 at 12:46
3

UPDATE 2021 / MySql v8.0.20 and later

The most upvoted answer advises to use the VALUES function which is now DEPRECATED for the ON DUPLICATE KEY UPDATE syntax. With v8.0.20 you get a deprecation warning with the VALUES function:

INSERT INTO chart (id, flag)
VALUES (1, 'FLAG_1'),(2, 'FLAG_2')
ON DUPLICATE KEY UPDATE id = VALUES(id), flag = VALUES(flag);

[HY000][1287] 'VALUES function' is deprecated and will be removed in a future release. Please use an alias (INSERT INTO ... VALUES (...) AS alias) and replace VALUES(col) in the ON DUPLICATE KEY UPDATE clause with alias.col instead

Use the new alias syntax instead:

INSERT INTO chart (id, flag) 
VALUES (1, 'FLAG_1'),(2, 'FLAG_2') AS aliased
ON DUPLICATE KEY UPDATE flag=aliased.flag;
EliteRaceElephant
  • 7,744
  • 4
  • 47
  • 62
1

just make a transaction statement, with multiple update statement and commit. In error case, you can just rollback modification handle by starting transaction.

START TRANSACTION;
/*Multiple update statement*/
COMMIT;

(This syntax is for MySQL, for PostgreSQL, replace 'START TRANSACTION' by 'BEGIN')

PrWhite
  • 19
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 10 '22 at 16:10
  • This is a easy smart hack – newuser Dec 07 '22 at 20:21
0

Try either multi-table update syntax

Try it copy and SQL query:

CREATE TABLE #temp (id int, name varchar(50))
CREATE TABLE #temp2 (id int, name varchar(50))

INSERT INTO #temp (id, name)
VALUES (1,'abc'), (2,'xyz'), (3,'mno'), (4,'abc')

INSERT INTO #temp2 (id, name) 
VALUES (2,'def'), (1,'mno1')

SELECT * FROM #temp
SELECT * FROM #temp2

UPDATE t
SET name = CASE WHEN t.id = t1.id THEN t1.name ELSE t.name END
FROM #temp t 
INNER JOIN #temp2 t1 on t.id = t1.id
 
select * from #temp
select * from #temp2

drop table #temp
drop table #temp2
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
0

UPDATE table name SET field name = 'value' WHERE table name.primary key

0

If you need to update several rows at a time, the alternative is prepared statement:

  • database complies a query pattern you provide the first time, keep the compiled result for current connection (depends on implementation).
  • then you updates all the rows, by sending shortened label of the prepared function with different parameters in SQL syntax, instead of sending entire UPDATE statement several times for several updates
  • the database parse the shortened label of the prepared function , which is linked to the pre-compiled result, then perform the updates.
  • next time when you perform row updates, the database may still use the pre-compiled result and quickly complete the operations (so the first step above can be omitted since it may take time to compile).

Here is PostgreSQL example of prepare statement, many of SQL databases (e.g. MariaDB,MySQL, Oracle) also support it.

Ham
  • 703
  • 8
  • 17
0

There have two another way :

one:

UPDATE `table_name`                                                             
SET                                                                
       `desc`   = CASE                                    
                    WHEN (`id_one`='1' AND `id_tow`='1') THEN '22222'                                                               
                    END                                                          
WHERE  (`id_one`, `id_tow`) IN ( ('1', '1') );

two

 UPDATE table_name
   SET field_to_update = CASE concat(key1, key2) 
                WHEN concat(1,1) THEN field_value1 
                WHEN concat(2,1) THEN feild_value2 
                ELSE feild_to_update
                END
   WHERE concat(key1, key2) IN ( concat(1, 1) , concat(2, 1) );
Tom
  • 333
  • 2
  • 8
0

I have found that using ON DUPLICATE KEY UPDATE on MySQL causes the auto increment id to skip values, which may be acceptable. I prefer to use this approach instead.

CREATE TABLE config
    (`config_name` varchar(255), `config_value` varchar(255))
;
    
INSERT INTO config
    (`config_name`, `config_value`)
VALUES
    ('name1', NULL),
    ('name2', NULL),
    ('name3', 'value3'),
    ('name4', 'value4'),
    ('name5', 'value5')
;

UPDATE config
JOIN (select 'name1' as config_name, 'value1' as config_value
     union all
     select 'name2', 'value2'
     union all
     select 'name4', 'updated value4'
     union all
     select 'name5', 'updated value5'
     ) x on x.config_name = config.config_name
   SET config.config_value = x.config_value; 

John Muraguri
  • 426
  • 7
  • 6