2009-07-24 2 views
15

Ich habe eine PL \ SQL-Skript, wo ich den Tabellennamen im Skript auf eine Variable festgelegt werden soll. Aus einigen Beispielen, die ich im Internet gefunden habe, habe ich den folgenden Code geschrieben. Der erste Abschnitt funktioniert, also denke ich, dass meine allgemeine Syntax korrekt ist, aber der zweite Abschnitt, in dem ich versuche, eine Variable für einen Tabellenname zu verwenden, enthält Fehler ("SQL-Fehler: ORA-00903: ungültiger Tabellenname").Wie verwende ich eine Variable in Oracle-Skript für den Tabellenname

Jeder weiß, was ich falsch mache ... Ich mache nicht viel PL \ SQL, vielleicht fehlt mir einfach etwas Offensichtliches.

--works 
variable numOfrecords number; 
exec :numOfrecords := 10; 
select * from customers2008 where rownum < :numOfrecords; 

--does not work 
variable tableNm CHAR; 
exec :tableNm := 'customers2008'; 
print tableNm; 
select * from :tableNm; 
+1

Nur zur Info: Basierend auf Ihren Beispielen verwenden Sie nicht wirklich PL/SQL. Ich denke du meinst, dass du ein SQLPlus-Skript hast. Technisch gesehen rufen Ihre exec-Befehle PL/SQL auf, aber insgesamt zeigen Sie hier SQLPlus-Befehle an. –

+1

Nun, technisch verwendet er beide - der variable Befehl im Skript deklariert eine PL/SQL Bindevariable. –

Antwort

6

Substitution variables Arbeit:

SQL> select * from &table_name; 
Enter value for table_name: dual 
old 1: select * from &table_name 
new 1: select * from dual 

D 
- 
X 
+0

Hah! Großartige Köpfe denken gleich - sogar die Doc-Verbindung ist identisch. –

+0

In der Tat! Die Links sind bis auf den Anker identisch :) –

14

Wenn Sie dieses Skript von sqlplus ausgeführt werden (was der Fall sein aussieht), können Sie den Befehl DEFINE verwenden möchten, die Sie sqlplus Substitutions Variablen erstellen können das ist nur gerade String-Ersetzung, zB:

define tableNm = 'customers2008' 
select * from &tableNm; 

Siehe Using Sql*Plus für weitere Informationen darüber, wie diese verwendet werden. Sie können Werte in das Skript von der Kommandozeile übergeben die vordefinierten Positionssubstitutionsvariablen, wie folgt aus:

define tableNm = &1 
select * from &tableNm; 

... und rufen Sie dann sqlplus wie so:

sqlplus user/[email protected] @myscript.sql customers2008 

Wenn Sie nicht tun Übergeben Sie einen Wert in der Befehlszeile, wird der Skript-Aufrufer aufgefordert, den Wert einzugeben.

Siehe Dave Costas Antwort unten für die Unterschiede zwischen Bindungs- und Substitutionsvariablen.

+0

Nur ein kleiner Fehler ist, dass Ihr SQLPlus Aufrufbeispiel nicht funktioniert (zumindest für mich). Um den Wert in der Befehlszeile zu übergeben, müssen Sie ein Skript aufrufen, z. 'sqlplus user/pwd @ server @ myscript customers2008'. –

+0

In der Tat! Bearbeitet und behoben. –

+0

liebe es! Tolles Zeug, Steve! – CFNinja

8

Um zu versuchen, eine Erklärung hinzuzufügen:

Die Methode, die Sie wird als eine Bindevariable verwenden wollten. Eine Bind-Variable wird in Oracle SQL durch einen Doppelpunkt gefolgt von einem Bezeichner identifiziert. Der Zweck einer Bind-Variablen ist, dass ihr Wert beim Analysieren der SQL-Anweisung nicht bekannt sein muss; Die Anweisung kann einmal analysiert und dann mehrfach ausgeführt werden, wobei unterschiedliche Werte an die Variable gebunden sind.

Damit eine SQL-Anweisung analysiert werden kann, müssen die beteiligten Tabellen- und Spaltennamen bekannt sein. Daher kann der Tabellenname nicht durch eine Bind-Variable dargestellt werden, da der Wert zur Parserzeit nicht bekannt ist.

Wenn Sie einfach SQL und Inline PL/SQl über SQLPlus ausführen, dann sind Substitutionsvariablen ein einfacher Weg, um mit diesem Problem umzugehen, wie Steve erklärte. Eine Substitutionsvariable wird durch ihren Wert ersetzt, wenn der SQLPlus-Client den Befehl liest, bevor er ihn zum Parsen an Oracle sendet.

7

Sie haben so etwas zu tun:

EXECUTE IMMEDIATE 'select * from' || tableNm; 

Dies liegt daran, Oracle nicht Bind-Variablen für die Tabelle ermöglichen (oder andere Objektnamen).

Es gibt erhebliche Auswirkungen auf die Sicherheit mit dem EXECUTE IMMEDIATE-Ansatz: Wenn der Wert von tableNm vom Benutzer bereitgestellt wird, sind Sie sehr anfällig für SQL injection-Angriffe.

Verwandte Themen