Sql 基于条件在同一表上使用Oracle合并

Sql 基于条件在同一表上使用Oracle合并,sql,oracle,oracle11g,upsert,sql-merge,Sql,Oracle,Oracle11g,Upsert,Sql Merge,我创建了一个Oracle序列,如下所示: CREATE SEQUENCE TASK_ID_SEQ START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE; TASK_ID nextval from TASK_ID_SEQ TASK_DATE SYSDATE TASK_TYPE <value fed from data> 我有一个数据库表TASK,如下所示: CREATE SEQUENCE TASK_ID_SEQ START WITH 1

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

CREATE SEQUENCE TASK_ID_SEQ START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;  
TASK_ID nextval from TASK_ID_SEQ
TASK_DATE   SYSDATE
TASK_TYPE   <value fed from data>
我有一个数据库表
TASK
,如下所示:

CREATE SEQUENCE TASK_ID_SEQ START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;  
TASK_ID nextval from TASK_ID_SEQ
TASK_DATE   SYSDATE
TASK_TYPE   <value fed from data>
或者应该是:

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

请提出建议。

您的业务规则表明日期和类型匹配。因此,您的代码有两个问题:

  • USING子句需要选择确定匹配所需的所有标准
  • ON子句需要测试确定匹配所需的所有标准
  • 此外,如果不需要更新现有记录,则可以忽略匹配时的分支。因此,合并语句应该如下所示:

    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)
    /   
    
    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
    
    7 rows selected.
    SQL>
    
    。。。上述合并应插入两行(数据源中的一行与现有行匹配)


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

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

    如果它只是一个insert语句,那么为什么不使用select?@user75ponic使用insert语句呢?原因有两个,一个是为了适应将来的更新,而只需要很少的更改,另一个是您是否预计合并会比insert慢?如果没有,为什么不呢?