我正在尝试使用合并,我可以看到以下错误
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)
我错过了什么?
语法非常规范。匹配条件属于单独的 ON 子句,并且必须放在括号中。 了解更多。
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 分支,用于确定匹配的行是更新还是删除。
连接条件错误:
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)