Oracle
 sql >> Database >  >> RDS >> Oracle

PLS-00103 creazione di una tabella esterna con SQL dinamico

Tutto da ORGANIZATION in poi viene visto come codice PL/SQL, non parte della tua istruzione SQL dinamica. Stai aggiungendo il nome della tabella a create table ma poi non aggiungere il resto come parte di quella stringa di istruzioni. Devi fare qualcosa come:

execute immediate 'create table ' || p_tab_name || '
( /* put column names and types here */ )                  
ORGANIZATION EXTERNAL 
(
TYPE ORACLE_LOADER
DEFAULT DIRECTORY DE_DUBFILE
ACCESS PARAMETERS 
    (
    RECORDS DELIMITED BY NEWLINE
    CHARACTERSET US7ASCII
    BADFILE     UPLOAD:''' || p_tab_name || '.bad''
    DISCARDFILE UPLOAD:''' || p_tab_name || '.dis''
    LOGFILE     UPLOAD:''' || p_tab_name || '.log''
    FIELDS TERMINATED BY '','' 
    optionally enclosed by ''"''
    MISSING FIELD VALUES ARE NULL
    (
    t1 ,t2,t3,t4,t5 date mask "YYYYMMDD" ,t6,t7,
    t8 ,t9, t10,t11
    )    
LOCATION (''' || DATAFILE || ''')    
)';

Nella prima riga il punto e virgola finale è stato sostituito con la concatenazione di una nuova stringa letterale. I riferimenti alle variabili p_tab_name e DATAFILE devono essere scomposti anche da quel letterale, richiedendo più virgolette singole e concatenazioni; e le virgolette singole che in realtà fanno parte della dichiarazione devono essere evitate raddoppiandole. Mancavano anche varie altre citazioni. Ciò che viene mostrato dovrebbe ora essere eseguito.

Ho anche cambiato il nome della tabella utilizzato solo in p_tab_name , ma è necessario specificare esplicitamente i nomi delle colonne e i tipi di dati. Non ha senso usare as select * ... per un tavolo esterno. Questa non è una sintassi legale, nemmeno prima di organization o dopo il resto se l'istruzione corrente. Suppongo che potresti estrarre queste informazioni da all_tab_columns e costruisci anche quella parte in modo dinamico, ma se la stai basando su un tavolo fisso dovresti comunque conoscerli.

Anche la tua logica di rilascio/creazione è disattivata:penso che tu voglia solo:

if n>0 then                                    
  execute immediate 'drop table ' || p_tab_name; 
end if;
execute immediate 'create table ' || p_tab_name || '
...

... quindi non devi ripetere l'istruzione create in entrambi i rami.

Ho anche corretto un paio di altri errori; PARAMETERS piuttosto che PARAMETER; FIELDS piuttosto che FILEDS; rimosso TRAILING NULLCOLS . Prova a eseguire il comando come SQL statico prima di convertirlo in dinamico. Potrebbero esserci ancora altri problemi.

E ho rimosso le ultime due colonne calcolate:

    DETL_CLMNS_HASH "ORA_HASH( :t4||:t7 )",
    KEY_CLMNS_HASH "ORA_HASH(:t1||:t2||:t5)")

Il ORACLE_LOADER conducente non consente manipolazioni del genere; SQL*Loader lo fa ma non sono esattamente la stessa cosa. Inoltre, non puoi definire colonne virtuali su una tabella esterna. Se la stai usando come tabella di staging per caricare i dati in un'altra tabella (reale), puoi calcolare quegli hash durante il trasferimento; altrimenti puoi creare una vista su questa tabella esterna che include le colonne calcolate.