2016-05-05 3 views
0

Ich schreibe eine merge Anweisung, um Daten in die Zieltabelle einzufügen.SQL zusammenführen, um dieselbe Tabelle für Einfügewerte zu lesen Problem

Voraussetzung: Die TEXT_SEQ Spalte muss Sequenznummern auf der Grundlage der aktuellen Werte der Tabelle basierend auf GROUP_ID und ADD_DATE

Diese erhalten ist, was habe ich bisher

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

Welchen Fehler bekommen Sie? – Boneist

+0

@Boneitist SQL-Fehler: ORA-00904: "B". "ADD_DATE": Ungültiger Bezeichner –

+0

Welche Version verwenden Sie? Das scheint in 11.2.0.4 kein Fehler zu sein. Ich bin mir nicht sicher, ob die Logik Sinn ergibt. Wenn es keine Übereinstimmung für Gruppe/Datum gibt, wird das aktuelle Maximum für diese Gruppe/Datum in der Unterabfrage immer Null erhalten? Und wenn Ihre Quelle mehrere Zeilen für die gleiche Gruppe/Datum hatte (ohne Übereinstimmung, mit irgendeiner Sequenz), würde die Zusammenführung ihnen alle einen Wert von 1 geben, denke ich. Vielleicht hast du verdeckt, was du zu viel tust? –

Antwort

0

in Fehler führt Wenn ich Ihre Anforderung richtig verstehe, können Sie dies mit einer Einfügung anstelle einer Zusammenführung tun. Wenn Sie Ihre Unterabfrage erweitern, können Sie alle source Zeilen mit einem generierten 'Sequenz'-Wert basierend auf Daten in der destination Tabelle abrufen. Beginnend mit einigen Dummy-Daten:

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'); 

und der aktuelle Maximalwert mit plus der analytischen Zeilennummer der Quelldaten für die Gruppe/Datum:

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 

Anschließend können Sie für Ihren Einsatz verwenden, dass:

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   

Sie auch die gleiche Abfrage wie die using Klausel einer merge verwenden könnte, und fügen Sie A.TEXT_SEQ = B.TEXT_SEQ zum ON Klausel; Da Sie aber nie eine Übereinstimmung haben werden, weil die Sequenz generiert wird, werden Sie immer in den Zweig WHEN NOT MATCHED gehen, so dass ich hier nichts über eine einfache Einfügung erkennen kann.

(Natürlich, using max(id) + 1m isn't safe, wenn Sie mehrere Sitzungen die Zieltabelle zur gleichen Zeit ändern können, aber Sie haben dieses Problem jedoch arrangieren Sie das Einfügen/Zusammenführen).

Verwandte Themen