2009-07-24 97 views
15

我有一个pl \ sql脚本,我想将脚本中使用的表名设置为一个变量。所以,从我在网上找到的一些例子中,我写下了下面的代码。第一部分的工作原理,所以我认为我的一般语法是正确的,但第二部分,我试图使用一个变量为一个表名错误(“SQL错误:ORA-00903:无效的表名”)。如何在表格名称的oracle脚本中使用变量

任何人都知道我在做什么错...我没有做很多PL \ SQL,所以也许我只是错过了一些明显的东西。

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

仅供参考:根据您的示例,您并未真正使用PL/SQL。我认为你的意思是你有一个SQLPlus脚本。从技术上讲,你的exec命令正在调用PL/SQL,但总体来说,你在这里展示的是SQLPlus命令。 – 2009-07-24 19:57:36

+1

嗯,从技术上说,他使用了两种 - 脚本中的变量命令声明了一个PL/SQL绑定变量。 – 2009-07-24 20:08:06

回答

6

Substitution variables工作:

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

哈!伟大的思想家都认为 - 即使文档链接是相同的。 – 2009-07-24 19:50:31

14

如果您正在从sqlplus的这个脚本(这看起来是如此),你要使用DEFINE命令,它允许你创建的sqlplus substition变量这只是直串替换,如:

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

Using Sql*Plus的更多信息,如何将这些被使用。您可以使用预定义的位置substition变量值传递到脚本的命令行,像这样:

define tableNm = &1 
select * from &tableNm; 

...,然后调用sqlplus中,像这样:

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

如果你不这样做在命令行传递一个值,脚本调用者将被提示输入值。

有关绑定和替换变量之间的差异,请参阅Dave Costa的回答。

8

要尝试添加一些说明:

您试图使用的方法被称为绑定变量。一个绑定变量在Oracle SQL中通过冒号后跟一个标识符来标识。绑定变量的目的是在解析SQL语句时不需要知道它的值;该语句可以被解析一次,然后使用绑定到变量的不同值执行多次。

为了解析SQL语句,必须知道涉及的表名和列名。所以表名不能用绑定变量来表示,因为在解析时这个值是不知道的。正如Steve解释的那样,如果您只是简单地通过SQLPlus执行SQL和内联PL/SQl,那么替换变量是解决此问题的简单方法。当SQLPlus客户端读取命令时,替换变量会替换为其值,然后它甚至会将其发送到Oracle进行分析。

7

你必须做这样的事情:

EXECUTE IMMEDIATE 'select * from' || tableNm; 

这是因为Oracle不允许表绑定变量(或任何其它对象名称)。

使用EXECUTE IMMEDIATE方法会产生重大的安全隐患:当tableNm值是用户提供的时,您可以全面打开SQL injection攻击。