sql >> Database teknologi >  >> RDS >> Oracle

Hvorfor kan jeg ikke bruge bindevariabler i DDL/SCL-sætninger i dynamisk SQL?

Bind-variabler er ikke tilladt i DDL-sætninger. Så følgende udsagn vil forårsage fejl:

  • Eksempel #1:DDL-sætning . Vil forårsage ORA-01027:bindevariabler er ikke tilladt for datadefinitionsoperationer

    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT :def_val )'
      USING 42;
    
  • Eksempel #2:DDL-sætning . Vil forårsage ORA-00904::ugyldig identifikator

    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( :col_name NUMBER )'
      USING var_col_name;
    
  • Eksempel #3:SCL-erklæring . Vil forårsage ORA-02248:ugyldig mulighed for ALTER SESSION

    EXECUTE IMMEDIATE
      'ALTER SESSION SET NLS_CALENDAR = :cal'
      USING var_calendar_option;
    

Problem

For at forstå, hvorfor dette sker, skal vi se på, hvordan dynamiske SQL-sætninger behandles.

Typisk beder et applikationsprogram brugeren om teksten til en SQL-sætning og værdierne af værtsvariabler, der bruges i sætningen. Derefter analyserer Oracle SQL-sætningen. Det vil sige, at Oracle undersøger SQL-sætningen for at sikre, at den følger syntaksregler og henviser til gyldige databaseobjekter. Parsing involverer også kontrol af databaseadgangsrettigheder , reservere nødvendige ressourcer og finde den optimale adgangssti.

Understregning tilføjet af besvareren

Bemærk, at parsingstrinet sker før binding af variabler til den dynamiske sætning. Hvis du undersøger ovenstående fire eksempler, vil du indse, at der ikke er nogen måde for parseren at garantere den syntaktiske gyldighed af disse dynamiske SQL-sætninger uden at kende værdierne for bindevariabler.

  • Eksempel #1 :Parser kan ikke fortælle, om bindeværdien vil være gyldig. Hvad nu hvis i stedet for USING 42 , programmør skrev USING 'forty-two' ?
  • Eksempel #2 :Parser kan ikke fortælle om :col_name ville være et gyldigt kolonnenavn. Hvad hvis det bundne kolonnenavn var 'identifier_that_well_exceeds_thirty_character_identifier_limit' ?
  • Eksempel #3 :Værdier for NLS_CALENDAR er indbygget i konstanter (for en given Oracle-version?). Parser kan ikke fortælle, om den bundne variabel vil have en gyldig værdi.

Så svaret er, at du ikke kan binde skemaelementer såsom tabelnavne, kolonnenavne i dynamisk SQL. Du kan heller ikke binde indbyggede konstanter .

Løsning

Den eneste måde at opnå refererende skemaelementer/konstanter dynamisk på er at bruge strengsammenkædning i dynamiske SQL-sætninger.

  • Eksempel #1:

    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT ' || to_char(42) || ')';
    
  • Eksempel #2:

    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table (' || var_col_name || ' NUMBER )';
    
  • Eksempel #3:

    EXECUTE IMMEDIATE
      'ALTER SESSION SET NLS_CALENDAR = ''' || var_calendar_option || '''';
    



  1. Avanceret SQL:Indsæt output fra den parametriserede tabelværdi-funktion i SQL-tabel

  2. Løsning af MySQL-fejl Deadlock fundet, når du forsøger at få lås; prøv at genstarte transaktionen

  3. Sådan viser du databaser og tabeller i PostgreSQL

  4. I SQL, hvordan man vælger de øverste 2 rækker for hver gruppe