2017-08-15 4 views
0

J'ai une table que j'ai besoin de mettre à jour avec certaines données d'une feuille de calcul Excel. Je pense à une requête dans ce sens:Utilisation des instructions "WITH" et "UPDATE" dans la même requête SQL

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 
) 
UPDATE mytable 
    SET name = (SELECT newvalue FROM temp WHERE mytable.name = temp.oldvalue) 

Mais Oracle ne semble pas avoir comme une déclaration « AVEC » et « Mettre à Jour » dans la même requête. Je reçois une erreur disant "Mot-clé SELECT manquant". Je l'ai découvert que je peux mettre la définition de table temporaire dans l'instruction SELECT, à savoir

SET name = (SELECT newvalue FROM (
     (SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION 
     (SELECT .....) 
     ) temp WHERE mytable.name = temp.oldvalue) 

Mais c'est horriblement, horriblement le code désordre pour définir une table comme ça au milieu de la requête. Je grince juste en y pensant. Il doit y avoir une meilleure façon de faire cela. Devrais-je mettre en place une table temporaire globale? Ou est-ce que je manque juste une syntaxe simple qui ferait de ce travail la manière originale?

+1

Je pense que créer une table temporaire est certainement la meilleure façon de le faire. –

Répondre

0

Vous pouvez utiliser une clause with dans une mise à jour; il vous 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 êtes désireux probablement uniquement les lignes de mise à jour qui existent dans la sous-requête de température, de sorte que vous auriez besoin d'un supplément where:

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; 

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

Vous devez tester les deux instructions pour voir laquelle est la plus performante sur vos données.

0

D'abord, je vous conseille d'utiliser ADHÈRE mise à jour comme celui-ci:

UPDATE 
(SELECT table1.value as OLD, table2.CODE as NEW 
FROM table1 
INNER JOIN table2 
ON table1.value = table2.DESC 
WHERE table1.UPDATETYPE='blah' 
) t 
SET t.OLD = t.NEW 

En outre, si vous avez le droit, créer la table et importer les données avec une solution ETL (Pentaho, SSIS, Suite Oracle BI). C'est propre et OK du point de vue de la performance.

Ou, utilisez les touches fléchées - plus d'informations se trouve sur le lien ci-dessous: http://www.adp-gmbh.ch/ora/plsql/cursors/for_update.html

2

Essayez ceci:

 
UPDATE mytable m 
    SET name = 
      (WITH temp 
       AS (SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM DUAL 
        UNION ALL /* Use UNION ALL instead of UNION in this case */ 
        SELECT 'efgh' AS oldvalue, 'klmn' AS newvalue FROM DUAL) 
      SELECT newvalue 
      FROM temp 
      WHERE temp.oldvalue = m.name) 

Ou, vous pouvez ust générer le script en insérant cette dans la cellule adjacente dans Excel:

="UPDATE YOUR_TABLE_NAME SET NAME="&CELL_WITH_NEW_VALUE&" WHERE NAME="&CELL_WITH_OLD_VALUE&"; COMMIT;" 

et faites glisser vers le bas jusqu'à la fin de la liste de valeurs. Après, exécutez ceci comme script et vous avez terminé!

+0

La réponse de Boneist a mieux fonctionné pour moi, mais c'est aussi une très bonne solution. +1 – schneiju