SQL - обновить несколько записей в одном запросе

У меня есть таблица - конфиг. Схема:config_name | config_value

И я хотел бы обновить несколько записей в одном запросе. Я пытаюсь так:

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

но этот запрос неверен:(

Вы можете мне помочь?

17 ответов

Решение

Попробуйте использовать синтаксис обновления нескольких таблиц

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';

Вот демоверсия SQLFiddle

или условное обновление

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');

Вот демоверсия SQLFiddle

Вы можете сделать это с помощью INSERT, как показано ниже:

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);

Это вставит новые значения в таблицу, но если первичный ключ будет продублирован (уже вставлен в таблицу), указанные вами значения будут обновлены, и та же запись не будет вставлена ​​во второй раз.

В моем случае я должен обновить записи, которые больше 1000, для этого вместо того, чтобы нажимать на запрос на обновление каждый раз, когда я предпочел это,

   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 - это идентификаторы пользователей, и для этих идентификаторов необходимо обновить base_id 999 и 88 соответственно. Это работает для меня.

Вместо этого

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';

ты можешь использовать

UPDATE staff SET salary = 1200 WHERE name IN ('Bob', 'Frank', 'John');

Может кому то будет полезно

для Postgresql 9.5 работает как брелок

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

этот SQL обновляет существующую запись и вставляет новую (2 в одном)

Решение Камиллы сработало. Превратил это в базовую функцию PHP, которая записывает оператор SQL. Надеюсь, это поможет кому-то еще.

    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;
    }

Выполните приведенный ниже код, чтобы обновить количество строк, где Parent ID - это идентификатор, из которого вы хотите получить данные, а Child ids - это идентификаторы, которые вам нужно обновить, поэтому вам просто нужно добавить родительский идентификатор и дочерние идентификаторы для обновления все строки вам нужны, используя небольшой скрипт.

    UPDATE [Table]
 SET couloumn1= (select couloumn1 FROM Table WHERE IDCouloumn = [PArent ID]),
     couloumn2= (select couloumn2 FROM Table WHERE IDCouloumn = [PArent ID]),
     couloumn3= (select couloumn3 FROM Table WHERE IDCouloumn = [PArent ID]),
     couloumn4= (select couloumn4 FROM Table WHERE IDCouloumn = [PArent ID]),
 WHERE IDCouloumn IN ([List of child Ids])

Выполните приведенный ниже код, если вы хотите обновить все записи во всех столбцах:

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

и если вы хотите обновить все столбцы определенной строки, выполните следующий код:

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

ОБНОВЛЕНИЕ 2021 / MySql v8.0.20 и новее

Самый популярный ответ советует использовать VALUESфункция, которая теперь УСТАРЕЛА для ON DUPLICATE KEY UPDATEсинтаксис. С v8.0.20 вы получаете предупреждение об устаревании с функцией VALUES:

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

[HY000] [1287] Функция «ЗНАЧЕНИЯ» устарела и будет удалена в следующем выпуске. Используйте псевдоним (INSERT INTO ... VALUES (...) AS псевдоним) и замените VALUES (col) в предложении ON DUPLICATE KEY UPDATE на alias.col.

Вместо этого используйте новый синтаксис псевдонима:

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

Предполагая, что у вас есть список значений для обновления в электронной таблице Excel с config_value в столбце A1 и config_name в B1, вы можете легко написать запрос, используя формулу Excel, например

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

INSERT INTO tablename
    (name, salary)
    VALUES 
        ('Bob', 1125),
        ('Jane', 1200),
        ('Frank', 1100),
        ('Susan', 1175),
        ('John', 1150)
        ON DUPLICATE KEY UPDATE salary = VALUES(salary);

просто сделайте оператор транзакции с несколькими операторами обновления и зафиксируйте. В случае ошибки вы можете просто откатить дескриптор модификации, запустив транзакцию.

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

(Этот синтаксис предназначен для MySQL, для PostgreSQL замените «START TRANSACTION» на «BEGIN»)

Если вам нужно обновить несколько строк за раз, альтернативой является подготовленный оператор :

  • база данных соответствует шаблону запроса, который вы предоставляете в первый раз, сохраните скомпилированный результат для текущего соединения (зависит от реализации).
  • затем вы обновляете все строки, отправляя сокращенную метку подготовленной функции с другими параметрами в синтаксисе SQL, вместо отправки всегоUPDATEзаявление несколько раз для нескольких обновлений
  • база данных анализирует сокращенную метку подготовленной функции , которая связана с предварительно скомпилированным результатом, затем выполняет обновления.
  • В следующий раз, когда вы выполняете обновление строк, база данных может по-прежнему использовать предварительно скомпилированный результат и быстро выполнять операции (поэтому первый шаг выше можно опустить, так как для компиляции может потребоваться время).

Вот пример оператора подготовки PostgreSQL , многие базы данных SQL (например, MariaDB,MySQL, Oracle) также поддерживают его.

Есть еще два способа:

один:

      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') );

два

       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) );

Попробуйте либо синтаксис обновления нескольких таблиц

Попробуйте скопировать и запросить SQL:

      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

ОБНОВЛЕНИЕ НАБОРАfield name= 'значение' ГДЕtable name.primary key

Я обнаружил, что используяON DUPLICATE KEY UPDATEв MySQL приводит к тому, что идентификатор автоматического увеличения пропускает значения, что может быть приемлемо. Вместо этого я предпочитаю использовать этот подход.

      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; 

Другие вопросы по тегам