sql >> Base de Datos >  >> RDS >> Oracle

PLS-00103 creando una tabla externa con SQL dinámico

Todo de ORGANIZATION en adelante se ve como código PL/SQL, no como parte de su declaración SQL dinámica. Está agregando el nombre de la tabla a create table pero luego no agregar el resto como parte de esa cadena de declaración. Tienes que hacer algo como:

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

En la primera línea, el punto y coma final se reemplazó con la concatenación de un nuevo literal de cadena. Las referencias a variables p_tab_name y DATAFILE también debe separarse de ese literal, lo que requiere más comillas simples y concatenación; y las comillas simples que en realidad son parte de la declaración deben escaparse duplicándolas. También faltaban varias otras citas. Lo que se muestra ahora debería ejecutarse.

También cambié el nombre de la tabla que se usa para simplemente p_tab_name , pero debe especificar los nombres de las columnas y los tipos de datos de forma explícita. No tiene sentido usar as select * ... para una mesa externa. Esa no es una sintaxis legal, tampoco antes de organization o después del resto si la declaración actual. Supongo que podrías extraer esa información de all_tab_columns y construya esa parte dinámicamente también, pero si la está basando en una tabla fija, debería conocerla de todos modos.

Tu lógica para soltar/crear también está desactivada. Creo que solo quieres:

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

... para que no tenga que repetir la declaración de creación en ambas ramas.

También he corregido un par de otros errores; PARAMETERS en lugar de PARAMETER; FIELDS en lugar de FILEDS; eliminado TRAILING NULLCOLS . Intente ejecutar el comando como SQL estático antes de convertirlo en dinámico. Todavía puede haber otros problemas.

Y eliminé las dos últimas columnas calculadas:

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

El ORACLE_LOADER conductor no permite manipulaciones como esa; SQL*Loader sí, pero no son exactamente iguales. Tampoco puede definir columnas virtuales en una tabla externa. Si está utilizando esto como una tabla de preparación para cargar datos en otra tabla (real), puede calcular esos hash durante la transferencia; de lo contrario, puede crear una vista sobre esta tabla externa que incluya las columnas calculadas.