Bindningsvariabler är inte tillåtna i DDL-satser. Så följande uttalanden kommer att orsaka fel:
-
Exempel #1:DDL-sats . Kommer att orsaka ORA-01027:bindningsvariabler är inte tillåtna för datadefinitionsoperationer
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT :def_val )' USING 42;
-
Exempel 2:DDL-sats . Kommer att orsaka ORA-00904::ogiltig identifierare
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( :col_name NUMBER )' USING var_col_name;
-
Exempel #3:SCL-sats . Kommer att orsaka ORA-02248:ogiltigt alternativ för ALTER SESSION
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_CALENDAR = :cal' USING var_calendar_option;
Problem
För att förstå varför detta händer måste vi titta på hur dynamiska SQL-satser bearbetas.
Vanligtvis frågar ett applikationsprogram användaren om texten i en SQL-sats och värdena för värdvariabler som används i satsen. Sedan analyserar Oracle SQL-satsen. Det vill säga, Oracle undersöker SQL-satsen för att säkerställa att den följer syntaxregler och hänvisar till giltiga databasobjekt. Parsning inbegriper också kontroll av databasåtkomsträttigheter , reservera nödvändiga resurser och hitta den optimala åtkomstvägen.
Betoning lagts till av svararen
Observera att analyssteget sker före binda alla variabler till den dynamiska satsen. Om du undersöker ovanstående fyra exempel kommer du att inse att det inte finns något sätt för parsern att garantera den syntaktiska giltigheten för dessa dynamiska SQL-satser utan att känna till värdena för bindningsvariabler.
- Exempel 1 :Parser kan inte avgöra om bindningsvärdet kommer att vara giltigt. Vad händer om istället för
USING 42
, skrev programmerarenUSING 'forty-two'
? - Exempel 2 :Parser kan inte avgöra om
:col_name
skulle vara ett giltigt kolumnnamn. Vad händer om det bundna kolumnnamnet var'identifier_that_well_exceeds_thirty_character_identifier_limit'
? - Exempel 3 :Värden för
NLS_CALENDAR
är inbyggda i konstanter (för en given Oracle-version?). Parser kan inte avgöra om den bundna variabeln kommer att ha ett giltigt värde.
Så svaret är att du inte kan binda schemaelement som tabellnamn, kolumnnamn i dynamisk SQL. Du kan inte heller binda inbyggda konstanter .
Lösning
Det enda sättet att uppnå hänvisning till schemaelement/konstanter dynamiskt är att använda strängsammansättning i dynamiska SQL-satser.
-
Exempel #1:
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT ' || to_char(42) || ')';
-
Exempel 2:
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table (' || var_col_name || ' NUMBER )';
-
Exempel 3:
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_CALENDAR = ''' || var_calendar_option || '''';