Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Warum kann ich Bind-Variablen in DDL/SCL-Anweisungen in dynamischem SQL nicht verwenden?

Bindevariablen sind in DDL-Anweisungen nicht zulässig. Die folgenden Anweisungen verursachen also Fehler:

  • Beispiel Nr. 1:DDL-Anweisung . Verursacht ORA-01027:Bindevariablen sind für Datendefinitionsoperationen nicht zulässig

    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT :def_val )'
      USING 42;
    
  • Beispiel #2:DDL-Anweisung . Verursacht ORA-00904::ungültige Kennung

    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( :col_name NUMBER )'
      USING var_col_name;
    
  • Beispiel #3:SCL-Anweisung . Verursacht ORA-02248:ungültige Option für ALTER SESSION

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

Problem

Um zu verstehen, warum dies geschieht, müssen wir uns ansehen, wie dynamische SQL-Anweisungen verarbeitet werden.

Typischerweise fordert ein Anwendungsprogramm den Benutzer auf, den Text einer SQL-Anweisung und die Werte der in der Anweisung verwendeten Host-Variablen einzugeben. Dann analysiert Oracle die SQL-Anweisung. Das heißt, Oracle untersucht die SQL-Anweisung, um sicherzustellen, dass sie den Syntaxregeln folgt und auf gültige Datenbankobjekte verweist. Beim Parsing werden auch die Zugriffsrechte der Datenbank geprüft , benötigte Ressourcen reservieren und den optimalen Zugriffspfad finden.

Hervorhebung durch Antworter hinzugefügt

Beachten Sie, dass der Parsing-Schritt vorher stattfindet Binden beliebiger Variablen an die dynamische Anweisung. Wenn Sie die obigen vier Beispiele untersuchen, werden Sie feststellen, dass es für den Parser keine Möglichkeit gibt, die syntaktische Gültigkeit dieser dynamischen SQL-Anweisungen zu garantieren, ohne die Werte für Bindevariablen zu kennen.

  • Beispiel Nr. 1 :Parser kann nicht sagen, ob der Bindungswert gültig ist. Was wäre, wenn statt USING 42 , Programmierer schrieb USING 'forty-two' ?
  • Beispiel Nr. 2 :Parser kann nicht erkennen, ob :col_name wäre ein gültiger Spaltenname. Was wäre, wenn der Name der gebundenen Spalte 'identifier_that_well_exceeds_thirty_character_identifier_limit' wäre ?
  • Beispiel Nr. 3 :Werte für NLS_CALENDAR sind eingebaute Konstanten (für eine bestimmte Oracle-Version?). Parser kann nicht sagen, ob die gebundene Variable einen gültigen Wert haben wird.

Die Antwort ist also, dass Sie keine Schemaelemente wie Tabellennamen oder Spaltennamen in dynamischem SQL binden können. Sie können auch keine eingebauten Konstanten binden .

Lösung

Die einzige Möglichkeit, Schemaelemente/Konstanten dynamisch zu referenzieren, ist die Verwendung von Zeichenfolgenverkettungen in dynamischen SQL-Anweisungen.

  • Beispiel Nr. 1:

    EXECUTE IMMEDIATE
      'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT ' || to_char(42) || ')';
    
  • Beispiel Nr. 2:

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

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