我正在尝试使用合并,我可以看到以下错误
ORA-00928:缺少SELECT关键字
merge into table using(select * from table on val = val1)
when matched then
(update set
val2 = val3 where val = val1)
when not matched then
(Insert query)
我错过了什么?
答案 0 :(得分:1)
语法很规范。匹配条件属于单独的ON子句,必须放在括号中。 Find out more
SQL> merge into t23 tgt
2 using ( select * from t23 ) q
3 on (tgt.col1 = q.col1)
4 when not matched then
5 insert values (q.col1, q.id+20, q.col2, q.date_time, q.qty, q.dt)
6 when matched then
7 update set tgt.col2 = q.col2 * 2
8 /
4 rows merged.
SQL>
“我到处使用同一张桌子,这可能是问题吗?”
不。正如我的示例查询所示,MERGE可以使用与源和目标相同的表运行。但是,问题是你为什么要那样做?所有行都匹配,在这种情况下,您正在执行update
或无匹配,这是insert ... select from
。
再次查看了你的伪查询,我想我可以看到你正在做什么。诀窍是确保ON子句中的条件将目标集中的一行与USING集中的一行匹配。否则它会投掷ORA-30926: unable to get a stable set of rows in the source tables
所以这是我之前查询的重新制作版本。
启动数据集(USING集):
SQL> select id, col1, qty, col2 from t23;
ID COL1 QTY C
------------------------------ ---------- ---------- -
ABCD0001 5 100 N
ABCD0002 10 10 N
ABCD0003 15 20 N
ABCD0004 20 -30 N
ABCD0005 35 20 N
ABCD0006 25 100 N
ABCD0007 30 30 N
ABCD0008 40 -30 N
8 rows selected.
SQL>
ON标准连接两列以保证稳定集:
SQL> merge into t23 tgt
2 using ( select * from t23 ) q
3 on (tgt.id = q.id
4 and tgt.col1 = tgt.qty)
5 when not matched then
6 insert values (q.id, q.col1+20, 'X', q.date_time, q.qty, q.dt)
7 when matched then
8 update set tgt.col2 = 'Y'
9 /
8 rows merged.
SQL>
结果是两次更新和六次插入......
SQL> select id, col1, qty, col2 from t23;
ID COL1 QTY C
------------------------------ ---------- ---------- -
ABCD0001 5 100 N
ABCD0002 10 10 Y
ABCD0003 15 20 N
ABCD0004 20 -30 N
ABCD0005 35 20 N
ABCD0006 25 100 N
ABCD0007 30 30 Y
ABCD0008 40 -30 N
ABCD0008 60 -30 X
ABCD0004 40 -30 X
ABCD0001 25 100 X
ABCD0003 35 20 X
ABCD0006 45 100 X
ABCD0005 55 20 X
14 rows selected.
SQL>
这种策略的明显危险是主要的碰撞。我的桌子是一个小包,没有主键。在现实生活中,您的表应该有一个主键,您需要在INSERT子句中处理它。
有趣的是,UPDATE分支中的WHERE子句是合法语法(尽管在OP的示例中它是多余的,因为它复制了ON条件)。对原始数据集运行此MERGE会合并六行(六个插入,无更新):
merge into t23 tgt
using ( select * from t23 ) q
on (tgt.id = q.id
and tgt.col1 = tgt.qty)
when not matched then
insert values (q.id, q.col1+20, 'X', q.date_time, q.qty, q.dt)
when matched then
update set tgt.col2 = 'Y'
where tgt.col2 = 'Z'
/
WHERE子句仅适用于MATCHED分支,用于确定匹配的行是更新还是删除。
答案 1 :(得分:0)
连接条件错误:
merge into table using (
select * from table
) on val = val1 --<< needs to go outside of the sub-select
when matched then
(update set
val2 = val3 where val = val1)
when not matched then
(Insert query)