sql >> Databasteknik >  >> RDS >> Oracle

Varför kan jag inte använda bindningsvariabler i DDL/SCL-satser i dynamisk SQL?

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 programmeraren USING '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 || '''';
    



  1. Bästa sättet att göra kapslad case-satslogik i SQL Server

  2. InMemory DUBLIKAT Förvirring i Oracle RAC

  3. DNA vs moderna säkerhetskopieringsmetoder:Framtiden för datalagring

  4. SQL Server AlwaysOn ( Availability Group ) Arkitektur och Steg för Steg Installation - 3 Manuell misslyckande över steg