MySQL - ОБНОВИТЬ несколько строк с разными значениями в одном запросе

139

Я пытаюсь понять, как ОБНОВИТЬ несколько строк с разными значениями, и я просто не понимаю. Решение есть везде, но мне кажется, что это трудно понять.

Например, три обновления в 1 запрос:

UPDATE table_users
SET cod_user = '622057'
    , date = '12082014'
WHERE user_rol = 'student'
    AND cod_office = '17389551'; 

UPDATE table_users
SET cod_user = '2913659'
    , date = '12082014'
WHERE user_rol = 'assistant'
    AND cod_office = '17389551'; 

UPDATE table_users
SET cod_user = '6160230'
    , date = '12082014'
WHERE user_rol = 'admin'
    AND cod_office = '17389551'; 

Я прочитал пример, но я действительно не понимаю, как сделать запрос. то есть:

UPDATE table_to_update
SET cod_user= IF(cod_office = '17389551','622057','2913659','6160230')
    ,date = IF(cod_office = '17389551','12082014')
WHERE ?? IN (??) ;

Я не совсем ясно, как сделать запрос, если есть несколько условий в ГДЕ и в условии ЕС .. какие-либо идеи?

franvergara66
источник
Отвечает ли это на ваш вопрос? Несколько обновлений в MySQL
PeterPan666

Ответы:

188

Вы можете сделать это следующим образом:

UPDATE table_users
    SET cod_user = (case when user_role = 'student' then '622057'
                         when user_role = 'assistant' then '2913659'
                         when user_role = 'admin' then '6160230'
                    end),
        date = '12082014'
    WHERE user_role in ('student', 'assistant', 'admin') AND
          cod_office = '17389551';

Я не понимаю ваш формат даты. Даты должны храниться в базе данных с использованием собственных типов даты и времени.

Гордон Линофф
источник
как я могу сделать, чтобы обновление выполнялось, если запись уже существует
franvergara66
1
@ franvergara66. , , Я не понимаю ваш комментарий. updateЭто влияет только на записи, которые уже существуют.
Гордон Линофф
Извините, мой английский сэр, когда я пытаюсь сделать обновление, mysql выдаёт мне ошибку: # 1062 - Дублирующая запись 'XXX' для ключа 'PRIMARY'. Что происходит, когда я пытаюсь обновить запись с тем же значением, которое у нее уже было, есть ли способ пропустить обновление, если текущее значение совпадает с обновлением?
franvergara66
1
@ franvergara66. , , У вас может быть другая проблема. Если cod_userэто первичный ключ, а значения перемешиваются, то, вероятно, лучшим вариантом является многократное обновление.
Гордон Линофф
1
да, я вижу, реальная проблема в том, что есть несколько помощников, затем при попытке сделать обновление целостность первичного ключа нарушается. Спасибо вам большое за ваше время.
franvergara66
109

MySQL позволяет более читабельный способ объединить несколько обновлений в один запрос. Похоже, что это лучше подходит для сценария, который вы описываете, его гораздо легче читать, и он позволяет избежать тех сложных условий, которые трудно распутать.

INSERT INTO table_users (cod_user, date, user_rol, cod_office)
VALUES
('622057', '12082014', 'student', '17389551'),
('2913659', '12082014', 'assistant','17389551'),
('6160230', '12082014', 'admin', '17389551')
ON DUPLICATE KEY UPDATE
 cod_user=VALUES(cod_user), date=VALUES(date)

Это предполагает, что user_rol, cod_officeкомбинация является первичным ключом. Если только один из них является первичным ключом , добавьте другое поле в список ОБНОВЛЕНИЕ. Если ни один из них не является первичным ключом (что кажется маловероятным), тогда этот подход всегда будет создавать новые записи - вероятно, не то, что требуется.

Однако такой подход облегчает построение утверждений и делает его более лаконичным.

Trevedhek
источник
4
Спасибо! Это то, что я искал долгое время самым чистым способом, я не мог понять этот синтаксис, в частности cod_user=VALUES(cod_user), ..., даже из официальных документов MySQL 5.6
Юрий Дьячков
18
Примечание: это добавит новые строки, если ключ не существует в таблице, что приведет к нежелательным записям.
Фараз
1
Хитро использовать никогда не вставляя IODKU, но очень элегантно.
Том Десп
И обратите внимание, что для этого подхода требуется, чтобы первичный ключ был задан для таблицы.
FlameStorm
5
Это не сработает, если вы опустите столбцы, которые не могут быть нулевыми, поскольку sql все еще пытается создать новую запись, прежде чем приступить к обновлению.
Арно ван Оордт
15

Вы можете использовать CASEоператор для обработки нескольких сценариев if / then:

UPDATE table_to_update 
SET  cod_user= CASE WHEN user_rol = 'student' THEN '622057'
                   WHEN user_rol = 'assistant' THEN '2913659'
                   WHEN user_rol = 'admin' THEN '6160230'
               END
    ,date = '12082014'
WHERE user_rol IN ('student','assistant','admin')
  AND cod_office = '17389551';
Харт CO
источник
1
Вы сделали опечатку в конце оператора CASE: у вас есть 2 запятых рядом друг с другом.
pmrotule
8
update table_name
set cod_user = 
    CASE 
    WHEN user_rol = 'student' THEN '622057'
    WHEN user_rol = 'assistant' THEN '2913659'
    WHEN user_rol = 'admin' THEN '6160230'?
    END,date = '12082014'

WHERE user_rol IN ('student','assistant','admin')
AND cod_office = '17389551';
Акшай Бхан
источник
0

Расширить на @Trevedhek ответ ,

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

ПРИМЕЧАНИЕ. Это не безопасно для транзакций.

Это можно сделать с помощью временной таблицы.

Шаг 1: Создайте ключи временной таблицы и столбцы, которые вы хотите обновить

CREATE TEMPORARY TABLE  temp_table_users
(
    cod_user varchar(50)
    , date varchar(50)
    , user_rol varchar(50)
    ,  cod_office varchar(50)
) ENGINE=MEMORY

Шаг 2: Вставьте значения в временную таблицу

Шаг 3: Обновите исходную таблицу

UPDATE table_users t1
JOIN temp_table_users tt1 using(user_rol,cod_office)
SET 
t1.cod_office = tt1.cod_office
t1.date = tt1.date

Шаг 4: Удалите временную таблицу

научно-консультативный комитет
источник
0
UPDATE Table1 SET col1= col2 FROM (SELECT col2, col3 FROM Table2) as newTbl WHERE col4= col3

Здесь col4 и col1 находятся в таблице1. col2 и col3 находятся в таблице 2.
Я пытаюсь обновить каждый col1, где col4 = col3 различное значение для каждой строки

Анкит Гири
источник
-1

Я сделал это так:

<update id="updateSettings" parameterType="PushSettings">
    <foreach collection="settings" item="setting">
        UPDATE push_setting SET status = #{setting.status}
        WHERE type = #{setting.type} AND user_id = #{userId};
    </foreach>
</update>

где PushSettings

public class PushSettings {

    private List<PushSetting> settings;
    private String userId;
}

работает нормально

ru51an
источник
автору нужен 1 запрос, ясно, что он может сделать это с помощью foreach, который сделает несколько запросов
Христо93,