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_COLest défini pour être non nul.