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

Por que não posso usar variáveis ​​de ligação em instruções DDL/SCL em SQL dinâmico?


As variáveis ​​de ligação não são permitidas em instruções DDL. Portanto, as seguintes declarações causarão erros:

  • Exemplo nº 1:instrução DDL . Causará ORA-01027:variáveis ​​de ligação não permitidas para operações de definição de dados
    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT :def_val )'
      USING 42;
    

  • Exemplo nº 2:instrução DDL . Causará ORA-00904::identificador inválido
    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( :col_name NUMBER )'
      USING var_col_name;
    

  • Exemplo nº 3:instrução SCL . Causará ORA-02248:opção inválida para ALTER SESSION
    EXECUTE IMMEDIATE
      'ALTER SESSION SET NLS_CALENDAR = :cal'
      USING var_calendar_option;
    

Problema


Para entender por que isso acontece, precisamos examinar Como as instruções SQL dinâmicas são processadas.

Normalmente, um programa aplicativo solicita ao usuário o texto de uma instrução SQL e os valores das variáveis ​​do host usadas na instrução. Em seguida, o Oracle analisa a instrução SQL. Ou seja, o Oracle examina a instrução SQL para garantir que ela siga as regras de sintaxe e se refira a objetos de banco de dados válidos. A análise também envolve a verificação dos direitos de acesso ao banco de dados , reservando os recursos necessários e encontrando o caminho de acesso ideal.

Ênfase adicionada pelo respondente

Observe que a etapa de análise ocorre antes vinculando quaisquer variáveis ​​à instrução dinâmica. Se você examinar os quatro exemplos acima, perceberá que não há como o analisador garantir a validade sintática dessas instruções SQL dinâmicas sem conhecer os valores das variáveis ​​de ligação.
  • Exemplo nº 1 :O analisador não pode dizer se o valor de ligação será válido. E se em vez de USING 42 , o programador escreveu USING 'forty-two' ?
  • Exemplo nº 2 :O analisador não pode dizer se :col_name seria um nome de coluna válido. E se o nome da coluna vinculada fosse 'identifier_that_well_exceeds_thirty_character_identifier_limit' ?
  • Exemplo nº 3 :Valores para NLS_CALENDAR são construídas em constantes (para uma determinada versão do Oracle?). O analisador não pode dizer se a variável vinculada terá um valor válido.

Portanto, a resposta é que você não pode vincular elementos de esquema, como nomes de tabelas, nomes de colunas em SQL dinâmico. Nem você pode vincular constantes incorporadas .

Solução


A única maneira de fazer referência a elementos/constantes de esquema dinamicamente é usar a concatenação de strings em instruções SQL dinâmicas.

  • Exemplo nº 1:
    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT ' || to_char(42) || ')';
    

  • Exemplo nº 2:
    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table (' || var_col_name || ' NUMBER )';
    

  • Exemplo nº 3:
    EXECUTE IMMEDIATE
      'ALTER SESSION SET NLS_CALENDAR = ''' || var_calendar_option || '''';