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