MySQL - METTRE À JOUR plusieurs lignes avec des valeurs différentes dans une seule requête

139

J'essaie de comprendre comment METTRE À JOUR plusieurs lignes avec des valeurs différentes et je ne comprends tout simplement pas. La solution est partout mais pour moi, cela me semble difficile à comprendre.

Par exemple, trois mises à jour en une requête:

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

J'ai lu un exemple, mais je ne comprends vraiment pas comment faire la requête. c'est à dire:

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

Je ne suis pas tout à fait clair comment faire la requête s'il y a plusieurs conditions dans la condition WHERE et dans la condition IF .. des idées?

franvergara66
la source
Est-ce que cela répond à votre question? Mises à jour multiples dans MySQL
PeterPan666

Réponses:

188

Vous pouvez le faire de cette façon:

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

Je ne comprends pas votre format de date. Les dates doivent être stockées dans la base de données en utilisant des types de date et d'heure natifs.

Gordon Linoff
la source
comment je peux faire pour que la mise à jour soit exécutée, si l'enregistrement existe déjà
franvergara66
1
@ franvergara66. . . Je ne comprends pas votre commentaire. updates n'affectent que les enregistrements qui existent déjà.
Gordon Linoff
Excusez mon anglais monsieur, lorsque j'essaye de faire une mise à jour mysql, donnez-moi l'erreur: # 1062 - Dupliquer l'entrée 'XXX' pour la clé 'PRIMARY'. C'est le cas lorsque j'essaye de mettre à jour un enregistrement avec la même valeur qu'il avait déjà, existe-t-il un moyen d'ignorer la mise à jour si la valeur actuelle est la même que celle mise à jour?
franvergara66
1
@ franvergara66. . . Vous pouvez avoir un problème différent. Si cod_userest une clé primaire et que les valeurs sont mélangées, alors plusieurs mises à jour sont probablement le meilleur itinéraire.
Gordon Linoff
1
oui, je vois, le vrai problème est qu'il y a plusieurs assistants, alors lorsque vous essayez de faire une mise à jour, l'intégrité de la clé primaire est violée. Merci beaucoup pour votre temps.
franvergara66
109

MySQL offre un moyen plus lisible de combiner plusieurs mises à jour en une seule requête. Cela semble mieux correspondre au scénario que vous décrivez, est beaucoup plus facile à lire et évite ces conditions multiples difficiles à démêler.

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)

Cela suppose que la user_rol, cod_officecombinaison est une clé primaire. Si une seule de ces clés est la clé primaire , ajoutez l'autre champ à la liste UPDATE. Si aucune d'elles n'est une clé primaire (cela semble peu probable), cette approche créera toujours de nouveaux enregistrements - probablement pas ce que l'on souhaite.

Cependant, cette approche rend les déclarations préparées plus faciles à construire et plus concises.

Trevedhek
la source
4
Je vous remercie! C'est ce que je cherchais depuis longtemps, de la manière la plus propre, je ne pouvais pas comprendre cette syntaxe, en particulier cod_user=VALUES(cod_user), ..., même à partir de la documentation officielle MySQL 5.6
Yuriy Dyachkov
18
Remarque: Cela ajoutera de nouvelles lignes si la clé n'existe pas dans la table, ce qui entraînera des enregistrements indésirables.
Faraz
1
Difficile d'utiliser un IODKU jamais insérable, mais très élégant.
Tom Desp
Et notez que cette approche nécessite que la clé primaire soit définie pour la table.
FlameStorm
5
Cela ne fonctionne pas si vous omettez des colonnes qui ne peuvent pas être nulles, car sql tente toujours de créer un nouvel enregistrement avant de recourir à la mise à jour.
Arno van Oordt
15

Vous pouvez utiliser une CASEinstruction pour gérer plusieurs scénarios 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';
Hart CO
la source
1
Vous avez fait une faute de frappe à la fin de l'instruction CASE: vous avez 2 virgules l'une à côté de l'autre.
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';
Akshay Bhan
la source
0

Pour prolonger la réponse @Trevedhek ,

Dans le cas où la mise à jour doit être effectuée avec des clés non uniques, 4 requêtes seront nécessaires

REMARQUE: ce n'est pas sécurisé pour les transactions

Cela peut être fait à l'aide d'une table temporaire.

Étape 1: Créez une table temporaire clés et les colonnes que vous souhaitez mettre à jour

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

Étape 2: Insérez les valeurs dans la table temporaire

Étape 3: mettre à jour la table d'origine

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

Étape 4: Supprimez la table temporaire

Sab
la source
0
UPDATE Table1 SET col1= col2 FROM (SELECT col2, col3 FROM Table2) as newTbl WHERE col4= col3

Ici col4 et col1 sont dans le tableau 1. col2 et col3 sont dans le tableau2 J'essaye
de mettre à jour chaque col1 où col4 = col3 valeur différente pour chaque ligne

ankit giri
la source
-1

Je l'ai fait de cette façon:

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

où PushSettings est

public class PushSettings {

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

ça fonctionne bien

ru51an
la source
l'auteur veut 1 requête, il est clair qu'il peut le faire avec foreach, qui fera plusieurs requêtes
Hristo93