Oracle
 sql >> Base de données >  >> RDS >> Oracle

PLS-00103 création d'une table externe avec SQL dynamique

Tout de ORGANIZATION est considéré comme du code PL/SQL, et non comme une partie de votre instruction SQL dynamique. Vous ajoutez le nom de la table au create table mais sans ajouter le reste dans le cadre de cette chaîne d'instructions. Vous devez faire quelque chose comme :

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

Dans la première ligne, le point-virgule de fin a été remplacé par la concaténation d'un nouveau littéral de chaîne. Les références aux variables p_tab_name et DATAFILE doivent également être séparés de ce littéral, nécessitant davantage de guillemets simples et de concaténation ; et les guillemets simples qui font réellement partie de l'instruction doivent être échappés en les doublant. Il manquait également diverses autres citations. Ce qui est affiché devrait maintenant fonctionner.

J'ai également changé le nom de la table utilisé pour juste p_tab_name , mais vous devez spécifier explicitement les noms de colonne et les types de données. Cela n'a pas de sens d'utiliser as select * ... pour une table externe. Ce n'est pas une syntaxe légale, ni avant organization ou après le reste si la déclaration en cours. Je suppose que vous pourriez extraire ces informations de all_tab_columns et construisez également cette partie de manière dynamique, mais si vous la basez sur une table fixe, vous devriez quand même les connaître.

Votre logique de suppression/création est également erronée - je pense que vous voulez simplement :

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

... afin que vous n'ayez pas à répéter l'instruction de création dans les deux branches.

J'ai également corrigé quelques autres erreurs; PARAMETERS plutôt que PARAMETER; FIELDS plutôt que FILEDS; supprimé TRAILING NULLCOLS . Essayez d'exécuter la commande en tant que SQL statique avant de la convertir en dynamique. Il peut encore y avoir d'autres problèmes.

Et j'ai supprimé les deux dernières colonnes calculées :

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

Le ORACLE_LOADER chauffeur ne permet pas de telles manipulations ; SQL*Loader le fait mais ils ne sont pas exactement les mêmes. Vous ne pouvez pas non plus définir de colonnes virtuelles sur une table externe. Si vous l'utilisez comme table intermédiaire pour charger des données dans une autre table (réelle), vous pouvez calculer ces hachages pendant le transfert ; sinon vous pouvez créer une vue sur cette table externe qui inclut les colonnes calculées.