根据条件在相同 table 上使用 Oracle MERGE
Using Oracle MERGE on same table based on condition
我创建了一个 Oracle 序列如下:
CREATE SEQUENCE TASK_ID_SEQ START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
我有一个数据库 table TASK
如下:
TASK_ID nextval from TASK_ID_SEQ
TASK_DATE SYSDATE
TASK_TYPE <value fed from data>
如果 TASK_TYPE
尚未出现在 TASK
table 中 TASK_DATE
的日期,我需要插入一条新的 TASK
记录,否则忽略它。
以下语法正确吗?
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) . . .
请提出建议。
您的业务规则表明 DATE 和 TYPE 匹配。所以你的代码有两处错误:
- USING 子句需要 select 确定匹配所需的所有条件。
- ON 子句需要测试确定匹配所需的所有条件。
此外,如果您不需要更新现有记录,您可以省略 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>
我创建了一个 Oracle 序列如下:
CREATE SEQUENCE TASK_ID_SEQ START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
我有一个数据库 table TASK
如下:
TASK_ID nextval from TASK_ID_SEQ
TASK_DATE SYSDATE
TASK_TYPE <value fed from data>
如果 TASK_TYPE
尚未出现在 TASK
table 中 TASK_DATE
的日期,我需要插入一条新的 TASK
记录,否则忽略它。
以下语法正确吗?
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) . . .
请提出建议。
您的业务规则表明 DATE 和 TYPE 匹配。所以你的代码有两处错误:
- USING 子句需要 select 确定匹配所需的所有条件。
- ON 子句需要测试确定匹配所需的所有条件。
此外,如果您不需要更新现有记录,您可以省略 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>