Oracle
 sql >> Base de données >  >> RDS >> Oracle

Utilisation des instructions WITH et UPDATE dans la même requête SQL

Vous pouvez utiliser une clause with dans une mise à jour; il suffit de le faire au bon endroit :

UPDATE mytable
   SET name = (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
                            (SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
                           )
               SELECT newvalue
               FROM   temp
               WHERE  mytable.name = temp.oldvalue);

Cependant, vous souhaitez probablement mettre à jour uniquement les lignes qui existent dans la sous-requête temporaire, vous auriez donc besoin d'une clause where supplémentaire :

UPDATE mytable
   SET name = (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
                            (SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
                           )
               SELECT newvalue
               FROM   temp
               WHERE  mytable.name = temp.oldvalue)
WHERE  EXISTS (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
                            (SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
                           )
               SELECT NULL
               FROM   temp
               WHERE  mytable.name = temp.oldvalue);

Vous pouvez également utiliser une instruction MERGE :

merge into mytable tgt
  using (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
                      (SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
                     )
         SELECT mytable.rowid r_id,
                temp.newvalue
         FROM   temp
         inner  join mytable on mytable.name = temp.oldvalue) src
    on (tgt.rowid = src.r_id)
when matched then
update set tgt.name = src.newvalue;

N.B. vous devez vous joindre à la table réelle dans la requête source de l'instruction de fusion car vous essayez de mettre à jour la colonne qui est jointe, ce que vous ne pouvez pas faire dans une instruction de fusion - j'ai donc basculé la jointure de fusion sur joindre sur mytable.rowid.

Vous devrez tester les deux déclarations pour voir laquelle est la plus performante sur vos données.