Comportamento dell'istruzione Oracle Merge quando ora_rowscn è nella clausola USING
-
27-10-2019 - |
Domanda
Ho un'istruzione MERGE che mi fornisce il temuto messaggio di errore ORA-00904: invalid identifier
. Tieni presente che i problemi tipici con l'errore "identificatore non valido" non sono presenti qui: non sto cercando di aggiornare la colonna unita, né ho scritto male i nomi delle colonne. Sto tentando di utilizzare la pseudo colonna Oracle ORA_ROWSCN
nell'istruzione USING
della clausola SELECT
.
Con queste tabelle di esempio, provo a eseguire
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);
Se rimuovo la pseudocolonna ora_rowscn dalla clausola USING, non ricevo più il messaggio di errore e l'unione viene completata correttamente.
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);
Se invece inserisco la query in una VISTA, posso utilizzare ora_rowscn con successo:
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);
Esiste un modo per farlo senza creare una VISTA per la query? Devo farlo su molte tabelle come parte di un processo ETL e preferirei non dover creare diverse viste.
MODIFICA: Sulla base del suggerimento di Glenn nei commenti, ho provato a inserire la query in una sottoquery:
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);
Questa query fornisce ancora il messaggio di errore ORA-00904: invalid identifier
.
Ecco DDL per ricreare il problema.
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);
Soluzione
Ho eseguito il tuo SQL e ho ricevuto lo stesso errore (su 11.2.0.1).Quindi ho provato a eseguire il select
SELECT PRIMARY_KEY,
COALESCE (UPDATE_DT, CREATED_DT) update_dt,
ORA_ROWSCN AS rowscn
FROM MY_SOURCE_TABLE;
Ricevuto ancora l'errore ORA-00904: "UPDATE_DT": invalid identifier
.Poi ho notato che nel tuo DDL, la colonna su MY_SOURCE_TABLE
si chiama UPDATED_DT
(cioè con un carattere D
in più).Cambiare i riferimenti a quello nella tua dichiarazione MERGE
l'ha fatto funzionare per me, spero che aiuti.