2009-07-24 9 views
15

J'ai un script pl \ sql où je veux définir le nom de la table utilisée dans le script à une variable. Donc, à partir de quelques exemples que j'ai trouvés sur le web, j'ai écrit le code ci-dessous. La première section fonctionne, donc je pense que ma syntaxe générale est correcte, mais la deuxième section, où j'essaie d'utiliser une variable pour un nom de table il erreurs ("Erreur SQL: ORA-00903: nom de table invalide"). Tout le monde sait ce que je fais mal ... Je ne fais pas beaucoup de PL \ SQL alors peut-être que je manque juste quelque chose d'évident.comment utiliser une variable dans le script Oracle pour le nom de la table

--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

Juste pour info: Selon vos exemples, vous n'utilisez pas vraiment PL/SQL. Je pense que vous voulez dire que vous avez un script SQLPlus. Techniquement, vos commandes exec appellent PL/SQL mais dans l'ensemble ce que vous montrez ici sont des commandes SQLPlus. –

+1

Eh bien, techniquement, il utilise les deux - la commande variable du script déclare une variable de liaison PL/SQL. –

Répondre

6

Substitution variables travail:

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! Les grands esprits se ressemblent - même le lien doc est identique. –

+0

En effet! Les liens sont identiques jusqu'à l'ancre :) –

14

Si vous utilisez ce script de sqlplus (qui semble être le cas), vous souhaitez utiliser la commande DEFINE, ce qui vous permet de créer des variables sqlplus de Substition qui sont la substitution de chaîne tout droit, par exemple:

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

Voir Using Sql*Plus pour plus d'informations sur la façon dont elles sont utilisées. Vous pouvez transmettre des valeurs dans votre script à partir de la ligne de commande en utilisant les variables de position Substition prédéfinies, comme ceci:

define tableNm = &1 
select * from &tableNm; 

... puis invoquer sqlplus comme ceci:

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

Si vous n'êtes pas transmettre une valeur sur la ligne de commande, l'invocateur de script sera invité pour la valeur.

Voir la réponse de Dave Costa ci-dessous pour les différences entre les variables de liaison et de substitution.

+0

Seul un petit problème est que votre exemple d'invocation SQLPlus ne fonctionne pas (du moins pour moi). Pour passer la valeur sur la ligne de commande, vous devez appeler un script, par ex. 'sqlplus utilisateur/pwd @ serveur @myscript clients2008'. –

+0

En effet! Edité et fixé. –

+0

adore ça! super truc Steve! – CFNinja

8

Pour essayer d'ajouter quelques explications:

La méthode que vous essayez d'utiliser est appelé une variable bind . Une variable de rattachement est identifiée dans Oracle SQL par un signe deux-points suivi d'un identifiant. Le but d'une variable de liaison est que sa valeur n'a pas besoin d'être connue lors de l'analyse de l'instruction SQL; l'instruction peut être analysée une fois puis exécutée plusieurs fois avec différentes valeurs liées à la variable.

Pour qu'une instruction SQL soit analysée, les noms de table et de colonne impliqués doivent être connus. Le nom de la table ne peut donc pas être représenté par une variable de liaison, car la valeur ne serait pas connue au moment de l'analyse.

Si vous exécutez simplement SQL et PL/SQl en ligne via SQLPlus, les variables de substitution sont un moyen facile de résoudre ce problème, comme l'a expliqué Steve. Une variable de substitution est remplacée par sa valeur lorsque le client SQLPlus lit la commande, avant même de l'envoyer à Oracle pour l'analyse.

7

Vous devez faire quelque chose comme ceci:

EXECUTE IMMEDIATE 'select * from' || tableNm; 

En effet, Oracle ne permet pas de lier les variables de la table (ou tout autre nom d'objet).

L'approche EXECUTE IMMEDIATE a des implications importantes en termes de sécurité: lorsque la valeur de tableNm est fournie par l'utilisateur, vous êtes totalement ouvert aux attaques SQL injection.

Questions connexes