ORA-00928:合并时缺少SELECT关键字

时间:2015-06-03 22:10:37

标签: sql oracle sql-merge

我正在尝试使用合并,我可以看到以下错误

  

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)

我错过了什么?

2 个答案:

答案 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)