Verhalten der Oracle Merge-Anweisung, wenn sich ora_rowscn in der USING-Klausel befindet
-
27-10-2019 - |
Frage
Ich habe eine MERGE-Anweisung, die mir die gefürchtete ORA-00904: invalid identifier
-Fehlermeldung gibt. Beachten Sie, dass die typischen Probleme mit dem Fehler "Ungültiger Bezeichner" hier nicht vorhanden sind. Ich versuche weder, die verknüpfte Spalte zu aktualisieren, noch habe ich meine Spaltennamen falsch geschrieben. Ich versuche , den ORA_ROWSCN
der Orakel-Pseudospalte in der USING
-Anweisung der SELECT
-Klausel zu verwenden.
Mit diesen Beispieltabellen versuche ich auszuführen
MERGE INTO MY_MERGE_TABLE D
USING
(SELECT PRIMARY_KEY,
COALESCE (UPDATE_DT, CREATED_DT) update_dt,
ORA_ROWSCN AS rowscn
FROM MY_SOURCE_TABLE) S
ON (D.PRIMARY_KEY = S.PRIMARY_KEY)
WHEN MATCHED THEN
UPDATE SET D.update_dt = GREATEST(D.update_dt, S.update_dt),
D.rowscn = GREATEST(D.rowscn, S.rowscn)
WHEN NOT MATCHED THEN
INSERT (D.PRIMARY_KEY, D.UPDATE_DT, D.ROWSCN)
VALUES (S.PRIMARY_KEY, S.UPDATE_DT, S.ROWSCN);
Wenn ich die Pseudospalte ora_rowscn aus der USING-Klausel entferne, wird die Fehlermeldung nicht mehr angezeigt und die Zusammenführung wird erfolgreich abgeschlossen.
MERGE INTO MY_MERGE_TABLE D
USING
(SELECT PRIMARY_KEY,
COALESCE (UPDATE_DT, CREATED_DT) update_dt
FROM MY_SOURCE_TABLE) S
ON (D.PRIMARY_KEY = S.PRIMARY_KEY)
WHEN MATCHED THEN
UPDATE SET D.update_dt = GREATEST(D.update_dt, S.update_dt)
WHEN NOT MATCHED THEN
INSERT (D.PRIMARY_KEY, D.UPDATE_DT)
VALUES (S.PRIMARY_KEY, S.UPDATE_DT);
Wenn ich die Abfrage stattdessen in einer ANSICHT platziere, kann ich ora_rowscn erfolgreich verwenden:
CREATE VIEW MY_VIEW AS
SELECT PRIMARY_KEY,
COALESCE (UPDATE_DT, CREATED_DT) update_dt,
ORA_ROWSCN AS rowscn
FROM MY_SOURCE_TABLE;
MERGE INTO MY_MERGE_TABLE D
USING (SELECT PRIMARY_KEY, UPDATE_DT, ROWSCN FROM MY_VIEW) S
ON (D.PRIMARY_KEY = S.PRIMARY_KEY)
WHEN MATCHED THEN
UPDATE SET D.update_dt = GREATEST(D.update_dt, S.update_dt),
D.rowscn = GREATEST(D.rowscn, S.rowscn)
WHEN NOT MATCHED THEN
INSERT (D.PRIMARY_KEY, D.UPDATE_DT, D.ROWSCN)
VALUES (S.PRIMARY_KEY, S.UPDATE_DT, S.ROWSCN);
Gibt es eine Möglichkeit, dies zu tun, ohne eine ANSICHT für die Abfrage zu erstellen? Ich muss dies in vielen Tabellen als Teil eines ETL-Prozesses tun und würde es vorziehen, nicht mehrere Ansichten erstellen zu müssen.
BEARBEITEN:
Basierend auf Glenns Vorschlag in den Kommentaren habe ich versucht, die Abfrage in eine Unterabfrage einzufügen:
MERGE INTO MY_MERGE_TABLE D
USING
(WITH QRY AS
(SELECT PRIMARY_KEY,
COALESCE (UPDATE_DT, CREATED_DT) update_dt,
ORA_ROWSCN AS rowscn
FROM MY_SOURCE_TABLE)
SELECT ORDER_ID, UPDATE_DT, ROWSCN FROM QRY)
ON (D.PRIMARY_KEY = S.PRIMARY_KEY)
WHEN MATCHED THEN
UPDATE SET D.update_dt = GREATEST(D.update_dt, S.update_dt),
D.rowscn = GREATEST(D.rowscn, S.rowscn)
WHEN NOT MATCHED THEN
INSERT (D.PRIMARY_KEY, D.UPDATE_DT, D.ROWSCN)
VALUES (S.PRIMARY_KEY, S.UPDATE_DT, S.ROWSCN);
Diese Abfrage gibt mir immer noch die ORA-00904: invalid identifier
-Fehlermeldung.
Hier ist DDL, um das Problem neu zu erstellen.
CREATE TABLE MY_SOURCE_TABLE (
PRIMARY_KEY NUMBER,
CREATED_DT TIMESTAMP(6),
UPDATED_DT TIMESTAMP(6)
);
CREATE TABLE MY_MERGE_TABLE (
PRIMARY_KEY NUMBER,
UPDATED_DT TIMESTAMP(6),
ROWSCN NUMBER
);
INSERT INTO MY_SOURCE_TABLE (PRIMARY_KEY, CREATED_DT, UPDATED_DT)
VALUES (1, SYSDATE-2, SYSDATE);
INSERT INTO MY_SOURCE_TABLE (PRIMARY_KEY, CREATED_DT, UPDATED_DT)
VALUES (2, SYSDATE-1, NULL);
INSERT INTO MY_SOURCE_TABLE (PRIMARY_KEY, CREATED_DT, UPDATED_DT)
VALUES (3, SYSDATE-1, SYSDATE+1);
INSERT INTO MY_MERGE_TABLE (PRIMARY_KEY, UPDATED_DT, ROWSCN)
VALUES (1, SYSDATE-2, 0);
INSERT INTO MY_MERGE_TABLE (PRIMARY_KEY, UPDATED_DT, ROWSCN)
VALUES (2, SYSDATE-1, 0);
Lösung
Ich habe Ihr SQL ausgeführt und den gleichen Fehler erhalten (am 11.2.0.1).Dann habe ich versucht, die Auswahl auszuführen
SELECT PRIMARY_KEY,
COALESCE (UPDATE_DT, CREATED_DT) update_dt,
ORA_ROWSCN AS rowscn
FROM MY_SOURCE_TABLE;
Immer noch der ORA-00904: "UPDATE_DT": invalid identifier
-Fehler.Dann habe ich festgestellt, dass in Ihrer DDL die Spalte auf MY_SOURCE_TABLE
als UPDATED_DT
bezeichnet wird (d. H. Mit einem zusätzlichen D
-Zeichen).Das Ändern der Verweise darauf in Ihrer MERGE
-Anweisung hat bei mir funktioniert, hoffe, das hilft.