Oracle
 sql >> Datenbank >  >> RDS >> Oracle

PLS-00103 Erstellen einer externen Tabelle mit dynamischem SQL

Alles von ORGANIZATION wird als PL/SQL-Code angesehen, nicht als Teil Ihrer dynamischen SQL-Anweisung. Sie hängen den Tabellennamen an create table an aber dann den Rest nicht als Teil dieser Anweisungszeichenfolge anhängen. Sie müssen etwas tun wie:

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

In der ersten Zeile wurde das abschließende Semikolon durch die Verkettung eines neuen String-Literals ersetzt. Die Verweise auf Variablen p_tab_name und DATAFILE müssen auch aus diesem Literal herausgebrochen werden, was mehr einfache Anführungszeichen und Verkettungen erfordert; und die einfachen Anführungszeichen, die eigentlich Teil der Anweisung sind, müssen durch Verdoppelung maskiert werden. Es fehlten auch verschiedene andere Zitate. Was angezeigt wird, sollte jetzt ausgeführt werden.

Ich habe auch den verwendeten Tabellennamen in p_tab_name geändert , aber Sie müssen die Spaltennamen und Datentypen explizit angeben. Es macht keinen Sinn, as select * ... zu verwenden für einen externen Tisch. Das ist keine legale Syntax, auch nicht vor organization oder nach dem Rest, wenn die aktuelle Anweisung. Ich nehme an, Sie könnten diese Informationen aus all_tab_columns extrahieren und bauen Sie diesen Teil auch dynamisch, aber wenn Sie ihn auf einer festen Tabelle basieren, sollten Sie diese sowieso kennen.

Ihre Logik zum Ablegen/Erstellen ist auch ausgeschaltet - ich denke, Sie wollen nur:

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

... damit Sie die create-Anweisung nicht in beiden Branches wiederholen müssen.

Ich habe auch ein paar andere Fehler korrigiert; PARAMETERS statt PARAMETERS; FIELDS statt FILEDS; TRAILING NULLCOLS entfernt . Versuchen Sie, den Befehl als statisches SQL auszuführen, bevor Sie ihn in dynamisch umwandeln. Es können noch andere Probleme auftreten.

Und ich habe die letzten beiden berechneten Spalten entfernt:

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

Der ORACLE_LOADER Fahrer erlaubt solche Manipulationen nicht; SQL*Loader tut es, aber sie sind nicht genau gleich. Sie können auch keine virtuellen Spalten in einer externen Tabelle definieren. Wenn Sie dies als Staging-Tabelle verwenden, um Daten in eine andere (echte) Tabelle zu laden, können Sie diese Hashes während der Übertragung berechnen. Andernfalls können Sie eine Ansicht über diese externe Tabelle erstellen, die die berechneten Spalten enthält.