0

マージを使用しようとしていますが、次のエラーが表示されます

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)

私は何を取りこぼしたか?

4

2 に答える 2

1

構文は非常に規範的です。一致基準は別の 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 句の条件がターゲット セットの 1 つの行と USING セットの 1 つの行に一致するようにすることです。そうでなければ、それは投げます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 条件は、安定したセットを保証するために 2 つの列を結合します。

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>

結果は、2 回の更新と 6 回の挿入です...

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 を実行すると、6 行がマージされます (6 回の挿入、更新なし)。

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 分岐にのみ適用され、一致した行を更新または削除するかどうかを決定するために使用されます。

于 2015-06-04T03:46:53.660 に答える
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)
于 2015-06-03T22:16:37.590 に答える