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.