2017-05-09 4 views
3

J'ai créé une séquence Oracle comme ci-dessous:Utilisation d'Oracle MERGE sur la même table en fonction de la condition

CREATE SEQUENCE TASK_ID_SEQ START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE; 

J'ai une table de base de données TASK comme ci-dessous:

TASK_ID nextval from TASK_ID_SEQ 
TASK_DATE SYSDATE 
TASK_TYPE <value fed from data> 

Je dois d'insérer un nouveau TASK enregistrer si le TASK_TYPE n'apparaît pas déjà dans la table TASK pour la date dans TASK_DATE, sinon l'ignorer.

La syntaxe suivante est-elle correcte?

MERGE INTO TASK a 
USING (SELECT b.task_date FROM TASK b) 
ON (a.task_type = b.task_type) 
WHEN NOT MATCHED THEN 
[INSERT INTO TASK] 

Ou devrait-il être aussi:

MERGE INTO TASK a 
USING (SELECT b.task_date FROM TASK b) 
ON (a.task_type = b.task_type) 
WHEN MATCHED THEN 
[] 
WHEN MATCHED THEN 
[INSERT INTO TASK] 

Puis-je utiliser alternativement

MERGE INTO TASK USING (select 1 from DUAL) . . . 

S'il vous plaît ne suggèrent.

+0

S'il s'agit seulement d'un insert alors pourquoi ne pas utiliser une instruction insert en utilisant select? – user75ponic

+0

@ user75ponic deux raisons, l'une pour s'adapter à la mise à jour à l'avenir avec des changements minimes et d'autre part pensez-vous que la fusion sera plus lente que l'insertion? Si non, alors pourquoi pas? –

Répondre

3

Votre règle métier indique une correspondance sur DATE et TYPE. Il y a donc deux problèmes avec votre code:

  1. La clause USING doit sélectionner tous les critères nécessaires pour déterminer une correspondance.
  2. La clause ON doit tester tous les critères nécessaires pour déterminer une correspondance.

De même, si vous n'avez pas besoin de mettre à jour les enregistrements existants, vous pouvez omettre la branche WHEN MATCHED. Votre instruction MERGE doit donc ressembler à ceci:

merge into task 
using ( 
    select date '2017-05-08' as dt, 'BATTLE' as typ from dual union all 
    select date '2017-05-08' as dt, 'JUGGLE' as typ from dual union all 
    select date '2017-05-08' as dt, 'PLOT' as typ from dual) q 
on (task.task_date = q.dt 
    and task.task_type = q.typ) 
when not matched then 
    insert values (task_id_seq.nextval, q.dt, q.typ) 
/ 

Une démo. Compte tenu de ce point de départ ...

SQL> select * from task; 

    TASK_ID TASK_DATE TASK_TYPE 
---------- ---------- ---------- 
     1 2017-05-06 CLEAN 
     2 2017-05-06 BATTLE 
     3 2017-05-06 JUGGLE 
     4 2017-05-07 JUGGLE 
     5 2017-05-07 CLEAN 
     6 2017-05-07 NAP 
     7 2017-05-08 BATTLE 

7 rows selected. 
SQL> 

... MERGE ci-dessus doivent y insérer deux lignes (une ligne de la source de données correspond à une ligne existante).

SQL> merge into task 
    2 using ( 
    3  select date '2017-05-08' as dt, 'BATTLE' as typ from dual union all 
    4  select date '2017-05-08' as dt, 'JUGGLE' as typ from dual union all 
    5  select date '2017-05-08' as dt, 'PLOT' as typ from dual) q 
    6 on (task.task_date = q.dt 
    7  and task.task_type = q.typ) 
    8 when not matched then 
    9  insert values (task_id_seq.nextval, q.dt, q.typ) 
10/ 

2 rows merged. 

SQL> select * from task 
    2/

    TASK_ID TASK_DATE TASK_TYPE 
---------- ---------- ---------- 
     1 2017-05-06 CLEAN 
     2 2017-05-06 BATTLE 
     3 2017-05-06 JUGGLE 
     4 2017-05-07 JUGGLE 
     5 2017-05-07 CLEAN 
     6 2017-05-07 NAP 
     7 2017-05-08 BATTLE 
     9 2017-05-08 JUGGLE 
     10 2017-05-08 PLOT 

9 rows selected. 

SQL> 

La source de données ne sont pas tout à fait clair. Donc, dans l'exemple ci-dessus, j'ai généré un ensemble de tâches en utilisant DUAL. Si ce que vous voulez est de créer une nouvelle série de tâches pour aujourd'hui de l'ensemble d'hier la clause USING ressemblerait à ceci:

merge into task 
using ( 
    select trunc(sysdate) as dt, task_type as typ 
    from task 
    where task_date = trunc(sysdate) - 1) q 
on (task.task_date = q.dt 
    and task.task_type = q.typ) 
when not matched then 
    insert values (task_id_seq.nextval, q.dt, q.typ) 
/

En utilisant les mêmes données de départ comme avant cette version insère trois lignes:

SQL> select * from task; 

    TASK_ID TASK_DATE TASK_TYPE 
---------- ---------- ---------- 
     1 2017-05-06 CLEAN 
     2 2017-05-06 BATTLE 
     3 2017-05-06 JUGGLE 
     4 2017-05-07 JUGGLE 
     5 2017-05-07 CLEAN 
     6 2017-05-07 NAP 
     7 2017-05-08 BATTLE 
     11 2017-05-08 CLEAN 
     12 2017-05-08 JUGGLE 
     13 2017-05-08 NAP 

10 rows selected. 

SQL>