J'ai le tableau suivant que je dois mettre à jour:
MERGE INTO USER U USING ( -- Subquery that generates a list of values ) T ON (U.REF_COL = T.VALUE) WHEN MATCHED THEN UPDATE SET U.ACTIVE = 1 WHEN NOT MATCHED THEN UPDATE SET U.ACTIVE = 0
J'exécute les deux instructions UPDATE
suivantes séparément:
Déclaration-1
UPDATE USER SET ACTIVE = 0 WHERE REF_COL NOT IN ( -- Subquery that generates a list of values )
Déclaration-2
UPDATE USER SET ACTIVE = 1 WHERE REF_COL IN ( -- Subquery that generates a list of values )
La sous-requête qui génère une liste de valeurs est la même pour les deux requêtes UPDATE
.
Y a-t-il un moyen qui m'aidera à exécuter la requête immédiatement, comme MERGE
?
La requête suivante utilisant MERGE code > l'instruction n'est pas valide:
USER: | ID | ACTIVE | REF_COL | COL_2 | COL_3 | |----|--------|---------|-------|-------| | 1 | 1 | value | value | value | | 2 | 0 | value | value | value | | 3 | 1 | value | value | value |
Puisque la clause WHEN NOT MATCHED THEN
s'attend à avoir une instruction INSERT
. p>
4 Réponses :
Utilisez CASE
dans SET
UPDATE USER U SET U.ACTIVE = (CASE WHEN U.REF_COL IN (<subquery>) THEN 0 ELSE 1 END)
Je soupçonne que la sous-requête serait évaluée pour chaque ligne de USER
.
@TapasBose Si la sous-requête renvoie une liste statique de valeurs, elle sera mise en cache, ce qui signifie qu'elle ne sera exécutée qu'une seule fois.
@TapasBose certainement pas dans Oracle
Éviter la fusion
est certainement la meilleure solution.
pesudocode pour la fusion:
CREATE OR REPLACE PROCEDURE all_updates_in_user IS cursor c1 is<<query that generates a list of values>> BEGIN FOR rec in c1 LOOP UPDATE USER SET ACTIVE = 1 WHERE REF_COL IN rec.columnname; UPDATE USER SET ACTIVE = 0 WHERE REF_COL NOT IN rec.columnname; END LOOP; END;
oracle docs ressemble à: La clause merge_insert_clause spécifie les valeurs à insérer dans la colonne de la table cible si la condition de la clause ON est fausse. Si la clause d'insertion est exécutée, tous les déclencheurs d'insertion définis sur la table cible sont activés. Si vous omettez la liste de colonnes après le mot clé INSERT, le nombre de colonnes de la table cible doit correspondre au nombre de valeurs de la clause VALUES. vous ne pouvez pas utiliser la fusion ou deux mises à jour une pour la correspondance et une autre pour la non-correspondance.
vous devrez créer une procédure à la place.
MERGE into <target table> USING <souce table/view/result of subquery> ON <match condition> WHEN MATCHED THEN <update clause> <delete clause> WHEN NOT MATCHED THEN <insert clause>
Voici une version merge
avec exemple. Vous devez placer la logique dans la partie source :
merge into users tgt using ( select u.ref_col, nvl2(s.ref_col, 1, 0) active from users u left join subquery s on u.ref_col = s.ref_col ) src on (tgt.ref_col = src.ref_col) when matched then update set active = src.active;
exemple de dbfiddle retour
Salut, pourriez-vous s'il vous plaît vérifier la réponse que j'ai donnée. De plus, votre idée a fonctionné comme un charme, donc j'ai accepté la réponse.
En utilisant l'idée fournie par Ponder Stibbons dans sa réponse , j'ai créé ce qui suit mettre en doute; la logique supplémentaire que j'ai ajoutée est de filtrer uniquement les lignes pour lesquelles la valeur ACTIVE
doit être mise à jour:
MERGE INTO USER U USING ( SELECT TGT.ID, SRC.ACTIVE FROM USER TGT JOIN ( SELECT U.REF_COL, NVL2(T.REF_COL, 1, 0) AS ACTIVE FROM USER U LEFT JOIN ( -- Subquery that generates a list of values ) T ON T.REF_COL = U.REF_COL ) SRC ON TGT.REF_COL = SRC.REF_COL WHERE TGT.ACTIVE != SRC.ACTIVE ) F ON (U.ID = F.ID) WHEN MATCHED THEN UPDATE SET U.ACTIVE = F.ACTIVE
Semble bien. Si je comprends bien la ligne WHERE TGT.ACTIVE! = SRC.ACTIVE
, c'est parce que vous souhaitez mettre à jour uniquement les lignes qui diffèrent. Si la colonne USER.ACTIVE
ne contient pas / ne peut pas contenir de valeurs nulles, cela devrait fonctionner correctement.
Exactement. Le ACTIVE
est non nullable. Merci encore.
s'il vous plaît montrer la sous-requête!
@nikhilsugandh, la question que j'ai posée pour démontrer le problème d'une manière simple. Dans le cas réel, il y a beaucoup de tables associées et je ne peux pas exposer leur nom.
la colonne ref_col de la table user peut-elle contenir des valeurs nulles? Si tel est le cas, ces lignes doivent-elles également être mises à jour ou ignorées?
@Boneist, non le
REF_COL
est défini pour être non nul.