根据条件在同一个表上使用Oracle MERGE

时间:2017-05-09 04:34:41

标签: sql oracle oracle11g upsert sql-merge

我创建了一个Oracle序列,如下所示:

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

我有一个数据库表TASK,如下所示:

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

如果TASK表中的TASK_TYPE尚未显示TASK中的日期,我需要插入新的TASK_DATE记录,否则请忽略它。

以下语法是否正确?

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]

或者它应该是:

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]

我可以替代使用

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

请建议。

1 个答案:

答案 0 :(得分:3)

您的商家规则表示DATE和TYPE匹配。所以你的代码有两个问题:

  1. USING子句需要选择确定匹配所需的所有条件。
  2. ON子句需要测试确定匹配所需的所有标准。
  3. 此外,如果您不需要更新现有记录,则可以省略WHEN MATCHED分支。所以你的MERGE语句应该是这样的:

    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)
    /   
    

    演示。鉴于这个起点......

    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应插入两行(数据源中的一行与现有行匹配)。

    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> 
    

    数据来源并不完全清楚。所以在上面的例子中,我使用DUAL生成了一组任务。如果你想要的是从昨天的集合为今天创建一组新的任务,USING子句将如下所示:

    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)
    /
    

    使用与此版本之前相同的起始数据,插入三行:

    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>