sql >> Database >  >> RDS >> Oracle

Waarom kan ik geen bindvariabelen gebruiken in DDL/SCL-instructies in dynamische SQL?

Bindvariabelen zijn niet toegestaan ​​in DDL-instructies. De volgende uitspraken zullen dus fouten veroorzaken:

  • Voorbeeld #1:DDL-statement . Zal ORA-01027 veroorzaken:bindvariabelen niet toegestaan ​​voor bewerkingen voor gegevensdefinitie

    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT :def_val )'
      USING 42;
    
  • Voorbeeld #2:DDL-statement . Zal leiden tot ORA-00904::ongeldige identifier

    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( :col_name NUMBER )'
      USING var_col_name;
    
  • Voorbeeld #3:SCL-statement . Zal leiden tot ORA-02248:ongeldige optie voor ALTER SESSIE

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

Probleem

Om te begrijpen waarom dit gebeurt, moeten we kijken naar hoe dynamische SQL-statements worden verwerkt.

Gewoonlijk vraagt ​​een toepassingsprogramma de gebruiker om de tekst van een SQL-instructie en de waarden van hostvariabelen die in de instructie worden gebruikt. Vervolgens parseert Oracle de SQL-instructie. Dat wil zeggen, Oracle onderzoekt de SQL-instructie om er zeker van te zijn dat deze de syntaxisregels volgt en verwijst naar geldige database-objecten. Parsing omvat ook het controleren van databasetoegangsrechten , het reserveren van de benodigde middelen en het vinden van het optimale toegangspad.

Nadruk toegevoegd door beantwoorder

Merk op dat de parseerstap vóór . plaatsvindt het binden van variabelen aan de dynamische instructie. Als u de bovenstaande vier voorbeelden bekijkt, zult u zich realiseren dat de parser op geen enkele manier de syntactische geldigheid van deze dynamische SQL-instructies kan garanderen zonder de waarden voor bindvariabelen te kennen.

  • Voorbeeld #1 :Parser kan niet zeggen of de bindwaarde geldig is. Wat als in plaats van USING 42 , programmeur schreef USING 'forty-two' ?
  • Voorbeeld #2 :Parser kan niet zien of :col_name zou een geldige kolomnaam zijn. Wat als de afhankelijke kolomnaam 'identifier_that_well_exceeds_thirty_character_identifier_limit' was ?
  • Voorbeeld #3 :Waarden voor NLS_CALENDAR zijn ingebouwd in constanten (voor een bepaalde Oracle-versie?). Parser kan niet zeggen of de gebonden variabele een geldige waarde zal hebben.

Het antwoord is dus dat u geen schema-elementen zoals tabelnamen, kolomnamen in dynamische SQL kunt binden. Je kunt ook geen ingebouwde constanten binden .

Oplossing

De enige manier om dynamisch naar schema-elementen/constanten te verwijzen, is door tekenreeksen te gebruiken in dynamische SQL-instructies.

  • Voorbeeld #1:

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

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

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



  1. Dubbele records zoeken in MySQL

  2. Bool-ondersteuning Oracle SQL

  3. Problemen oplossen wanneer er geen werkthreads meer zijn

  4. SQL UNION-spiekbriefje met 10 eenvoudige en handige tips