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

Мені не зовсім зрозуміло, як виконати запит, якщо в ГДЕ та в умовах ІФ є кілька умов.


Чи відповідає це на ваше запитання? Кілька оновлень у 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. . . Я не розумію вашого коментаря. updates впливають лише на записи, які вже існують.
Гордон Лінофф

Вибачте, мій англійський пане, коли я намагаюся зробити оновлення mysql, дайте мені помилку: # 1062 - Дублікат запису "XXX" для клавіші "PRIMARY". Це робить, коли я намагаюся оновити запис з тим самим значенням, яке він уже мав, чи є якийсь спосіб пропустити оновлення, якщо поточне значення збігається з оновленим?
franvergara66

1
@ franvergara66. . . У вас може бути інша проблема. Якщо cod_userце первинний ключ, а значення пересуваються навколо, то, мабуть, найкращий маршрут є декількома оновленнями.
Гордон Лінофф

1
так, я бачу, справжня проблема полягає в тому, що є кілька помічників, то при спробі зробити оновлення цілісність первинного ключа порушується. Дуже дякую за ваш час.
franvergara66

108

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комбінація є первинним ключем. Якщо лише один із них є первинним ключем , додайте інше поле до списку UPDATE. Якщо жоден з них не є первинним ключем (що здається малоймовірним), такий підхід завжди створюватиме нові записи - можливо, не те, що потрібно.

Однак такий підхід полегшує складання підготовлених заяв і більш стислих.


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

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

це чудово працює


автор хоче 1 запит, зрозуміло, що він може це зробити з foreach, який зробить кілька запитів
Hristo93
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.