SQL - Mettre à jour plusieurs enregistrements dans une seule requête

132

J'ai table - config . Schéma: config_name | config_value

Et je voudrais mettre à jour plusieurs enregistrements en une seule requête. J'essaye comme ça:

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

mais cette requête est fausse :(

Pouvez-vous m'aider?

utilisateur3022527
la source
1
Quelle base de données utilisez-vous?
Hart CO
J'utilise la base de données MySQL.
user3022527
La mise à jour de Select pourrait être la réponse stackoverflow.com/questions/2334712/…
Jonathan Benn

Réponses:

167

Essayez l'une des syntaxes de mise à jour multi-tables

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

Voici la démo de SQLFiddle

ou mise à jour conditionnelle

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

Voici la démo de SQLFiddle

Peterm
la source
1
Oui, c'est bien, mais que faire quand je wolud aime mettre à jour 16 enregistrements en une seule requête? Je sholud utiliser JOIN x 16?
user3022527
19
Vous devriez mentionner ces détails importants dans votre question en premier lieu. Quoi qu'il en soit, voir la réponse mise à jour pour une autre solution (mise à jour conditionnelle).
peterm
1
Que sont t1 et t2 dans vos exemples?
Paul Brewczynski
1
Bonjour à vous aussi @PaulBrewczynski. Ce sont des alias de table et peuvent être écrits config AS t1là où ASest facultatif.
peterm
@peterm: les liens SQLFiddle sont rompus. Sinon, la technique de mise à jour conditionnelle fonctionne très bien. Merci!
Jonathan Benn
142

Vous pouvez l'accomplir avec INSERT comme ci-dessous:

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

Cela permet d'insérer de nouvelles valeurs dans la table, mais si la clé primaire est dupliquée (déjà insérée dans la table), les valeurs que vous spécifiez seraient mises à jour et le même enregistrement ne serait pas inséré une deuxième fois.

camille khalaghi
la source
26
un hack assez intelligent. Je suis ébahi.
Blaise
6
Non pris en charge pour Postgres voir: stackoverflow.com/questions/1109061/…
kevzettler
En outre, c'est un excellent moyen de transformer un peu de CSV (ou beaucoup) en une insertion / mise à jour / upsert de tableau avec quelques modifications de texte mineures!
wulftone
6
Ceci est une solution MySQL, pas Postgres ou MSSQL.
Rz Mk
1
Cela incrémentera l'identifiant d'auto-incrémentation, même si l'enregistrement n'est pas inséré ou mis à jour
Timo Huovinen
15

dans mon cas, je dois mettre à jour les enregistrements qui sont plus de 1000, pour cela au lieu de frapper la requête de mise à jour chaque fois que je préfère cela,

   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 sont les identifiants d'utilisateur et pour ces identifiants d'utilisateur, je dois mettre à jour respectivement base_id 999 et 88.Cela fonctionne pour moi.

vaibhav kulkarni
la source
L'un des meilleurs ici, a très bien fonctionné pour moi.
Shahrukh Anwar
7

peut-être que pour quelqu'un ce sera utile

pour Postgresql 9.5 fonctionne comme un charme

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

ce SQL met à jour l'enregistrement existant et en insère un nouveau (2 en 1)

Oleg Sobchuk
la source
1
Comme je peux le voir, id est pk pour la table selon votre requête. Supposons qu'il y ait 2 colonnes ou plus considérées comme pk (clé composite) ... Dans ce cas, quelle devrait être la bonne façon de vérifier le conflit.
Sritam Jagadev
6

La solution de Camille a fonctionné. Je l'ai transformé en une fonction PHP de base, qui écrit l'instruction SQL. J'espère que ceci aide quelqu'un d'autre.

    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;
    }
Adamk
la source
5

au lieu de cela

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

vous pouvez utiliser

UPDATE staff SET salary = 1200 WHERE name IN ('Bob', 'Frank', 'John');
Shuhad zaman
la source
3

Exécutez le code ci-dessous pour mettre à jour n nombre de lignes, où l'ID parent est l'ID dont vous souhaitez obtenir les données et les ID enfants sont les ID dont vous devez mettre à jour, il vous suffit donc d'ajouter l'ID parent et les ID enfants à mettre à jour toutes les lignes dont vous avez besoin en utilisant un petit script.

    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])
Harrish Selvarajah
la source
2

En supposant que vous ayez la liste des valeurs à mettre à jour dans une feuille de calcul Excel avec config_value dans la colonne A1 et config_name dans B1, vous pouvez facilement y écrire la requête en utilisant une formule Excel comme

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

Ivar
la source
1

Exécutez le code ci-dessous si vous souhaitez mettre à jour tous les enregistrements dans toutes les colonnes:

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

et si vous souhaitez mettre à jour toutes les colonnes d'une ligne particulière, exécutez le code ci-dessous:

update config set column1='value',column2='value'...columnN='value' where column1='value'
Jason Clark
la source
3
et si une valeur différente dans une ligne différente? par exemple UPDATE staff SET salaire = 1125 WHERE name = 'Bob'; UPDATE staff SET salaire = 1200 WHERE name = 'Jane'; UPDATE staff SET salaire = 1100 WHERE name = 'Frank'; UPDATE staff SET salaire = 1175 WHERE name = 'Susan'; UPDATE staff SET salaire = 1150 WHERE name = 'John';
Abdullah Nurum