2016-05-05 11 views
0

宛先テーブルにデータを挿入するためにmergeステートメントを記述しています。SQLをマージして挿入値の同じテーブルを読み込む問題

要件:GROUP_ID

このADD_DATEに基づいて、テーブルの現在値に基づいてシーケンス番号を取得する必要がありますTEXT_SEQ列には、私がこれまでにエラー

MERGE INTO destination a USING source b 
ON(A.GROUP_ID = B.GROUP_ID AND A.ADD_DATE = B.ADD_DATE) 
WHEN NOT MATCHED THEN 
INSERT (A.GROUP_ID ,A.ADD_DATE ,A.SOME_TEXT ,A.TEXT_SEQ) 
VALUES (B.GROUP_ID ,B.ADD_DATE ,B.SOME_TEXT , 
      (
       SELECT NVL(MAX(C.TEXT_SEQ),0) + 1 
       FROM DESTINATION C 
       WHERE C.GROUP_ID = B.GROUP_ID 
       AND C.ADD_DATE = B.ADD_DATE 
      ) 
     ) 
+1

どのようなエラーが表示されますか? – Boneist

+0

@Boneist SQLエラー:ORA-00904: "B"。 "ADD_DATE":無効な識別子 –

+0

どのバージョンを使用していますか?それは11.2.0.4ではエラーではないようです。私は論理が理にかなっているかどうか分からない。グループ/日付にマッチするものがない場合、サブクエリ内のそのグループ/日付の現在の最大値は常にnullになりますか?そして、あなたのソースに同じグループ/日付の複数の行があった場合(マッチしないで、シーケンスがあれば)、マージはそれらのすべてに1の値を与えます。あなたはあなたがやっていることをあまりにも曖昧にしているのでしょうか? –

答えて

0

が得られたものである 要件を正しく理解していれば、マージの代わりに挿入することでこれを行うことができます。サブクエリを拡張すると、destinationテーブルのデータに基づいて生成された 'sequence'値を持つすべてのsource行を取得できます。いくつかのダミーデータを皮切り:

CREATE TABLE DESTINATION (GROUP_ID NUMBER, ADD_DATE DATE, SOME_TEXT VARCHAR2(20), TEXT_SEQ NUMBER); 

INSERT INTO DESTINATION VALUES (42, DATE '2016-05-01', 'Foo 1', 1); 
INSERT INTO DESTINATION VALUES (42, DATE '2016-05-01', 'Foo 2', 2); 
INSERT INTO DESTINATION VALUES (42, DATE '2016-05-01', 'Foo 3', 3); 
INSERT INTO DESTINATION VALUES (42, DATE '2016-05-02', 'Bar 1', 1); 

CREATE TABLE SOURCE (GROUP_ID NUMBER, ADD_DATE DATE, SOME_TEXT VARCHAR2(20)); 

INSERT INTO SOURCE VALUES (42, DATE '2016-05-01', 'New foo 1'); 
INSERT INTO SOURCE VALUES (42, DATE '2016-05-01', 'New foo 2'); 
INSERT INTO SOURCE VALUES (42, DATE '2016-05-01', 'New foo 3'); 
INSERT INTO SOURCE VALUES (42, DATE '2016-05-02', 'New bar 1'); 
INSERT INTO SOURCE VALUES (42, DATE '2016-05-03', 'New baz 1'); 
INSERT INTO SOURCE VALUES (43, DATE '2016-05-02', 'New qux 1'); 

そして、現在の最大値を加えたグループ/日付のソースデータの解析行番号を使用して:

SELECT S.GROUP_ID, S.ADD_DATE, S.SOME_TEXT, 
    NVL(MAX(D.TEXT_SEQ), 0) 
    + (ROW_NUMBER() OVER (PARTITION BY S.GROUP_ID, S.ADD_DATE ORDER BY 1)) AS TEXT_SEQ 
FROM source s 
LEFT JOIN destination d 
ON D.GROUP_ID = S.GROUP_ID AND D.ADD_DATE = S.ADD_DATE 
GROUP BY S.GROUP_ID, S.ADD_DATE, S.SOME_TEXT 
/

    GROUP_ID ADD_DATE SOME_TEXT    TEXT_SEQ 
---------- ---------- -------------------- ---------- 
     42 2016-05-01 New foo 1      4 
     42 2016-05-01 New foo 2      5 
     42 2016-05-01 New foo 3      6 
     42 2016-05-02 New bar 1      2 
     42 2016-05-03 New baz 1      1 
     43 2016-05-02 New qux 1      1 

あなたは、あなたの挿入のためにそれを使用することができます。あなたはまた、マージのusing句と同じクエリを使用し、ON句にA.TEXT_SEQ = B.TEXT_SEQを追加することができ

INSERT INTO destination (GROUP_ID ,ADD_DATE ,SOME_TEXT ,TEXT_SEQ) 
SELECT ... 

6 rows inserted. 

SELECT GROUP_ID, ADD_DATE, TEXT_SEQ, SOME_TEXT 
FROM DESTINATION 
ORDER BY GROUP_ID, ADD_DATE, TEXT_SEQ; 

    GROUP_ID ADD_DATE  TEXT_SEQ SOME_TEXT   
---------- ---------- ---------- -------------------- 
     42 2016-05-01   1 Foo 1    
     42 2016-05-01   2 Foo 2    
     42 2016-05-01   3 Foo 3    
     42 2016-05-01   4 New foo 1   
     42 2016-05-01   5 New foo 2   
     42 2016-05-01   6 New foo 3   
     42 2016-05-02   1 Bar 1    
     42 2016-05-02   2 New bar 1   
     42 2016-05-03   1 New baz 1   
     43 2016-05-02   1 New qux 1   

。シーケンスがどのように生成されるかによってあなたは決して一致することはないので、あなたは常にWHEN NOT MATCHEDブランチに入るので、ここで簡単な挿入には何も得られません。

(もちろん、複数のセッションで同時に宛先テーブルを変更することができますが、その問題はありますが、挿入/マージの手配が必要な場合はusing max(id) + 1m isn't safe

関連する問題