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);
È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top