Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

PLS-00103 criando uma tabela externa com SQL dinâmico


Tudo de ORGANIZATION em diante está sendo visto como código PL/SQL, não como parte de sua instrução SQL dinâmica. Você está anexando o nome da tabela ao create table mas não anexando o resto como parte dessa string de instrução. Você precisa fazer 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 || ''')    
)';

Na primeira linha, o ponto e vírgula final foi substituído pela concatenação de um novo literal de string. As referências às variáveis ​​p_tab_name e DATAFILE devem ser separados desse literal também, exigindo mais aspas simples e concatenação; e as aspas simples que realmente fazem parte da declaração precisam ser evitadas dobrando-as. Havia várias outras citações faltando também. O que é mostrado agora deve ser executado.

Também alterei o nome da tabela usada apenas para p_tab_name , mas você precisa especificar os nomes das colunas e os tipos de dados explicitamente. Não faz sentido usar as select * ... para uma mesa externa. Isso não é sintaxe legal, também antes de organization ou depois do resto se a declaração atual. Suponho que você possa extrair essas informações de all_tab_columns e construa essa parte dinamicamente também, mas se você está baseando-a em uma tabela fixa, você deve conhecê-las de qualquer maneira.

Sua lógica para descartar/criar também está desativada - acho que você só quer:
if n>0 then                                    
  execute immediate 'drop table ' || p_tab_name; 
end if;
execute immediate 'create table ' || p_tab_name || '
...

... para que você não precise repetir a instrução create em ambas as ramificações.

Também corrigi alguns outros erros; PARAMETERS em vez de PARAMETER; FIELDS em vez de FILEDS; removido TRAILING NULLCOLS . Tente executar o comando como SQL estático antes de convertê-lo em dinâmico. Ainda pode haver outros problemas.

E eu removi as duas últimas colunas calculadas:
    DETL_CLMNS_HASH "ORA_HASH( :t4||:t7 )",
    KEY_CLMNS_HASH "ORA_HASH(:t1||:t2||:t5)")

O ORACLE_LOADER motorista não permite manipulações assim; SQL*Loader faz, mas eles não são exatamente os mesmos. Você também não pode definir colunas virtuais em uma tabela externa. Se você estiver usando isso como uma tabela de teste para carregar dados em outra tabela (real), poderá calcular esses hashes durante a transferência; caso contrário, você pode criar uma visão sobre esta tabela externa que inclui as colunas calculadas.