我有一个pl \ sql脚本,我想将脚本中使用的表名设置为变量。因此,从我在网上找到的一些例子中,我编写了下面的代码。第一部分工作,所以我认为我的一般语法是正确的,但第二部分,我尝试使用变量为表名称错误(“ SQL错误:ORA-00903:无效的表名“)。
任何人都知道我做错了什么......我没有做很多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;
答案 0 :(得分:14)
如果从sqlplus运行此脚本(看起来是这种情况),则需要使用DEFINE命令,该命令允许您创建只是直接字符串替换的sqlplus子代变量,例如:
define tableNm = 'customers2008'
select * from &tableNm;
有关如何使用这些内容的详细信息,请参阅Using Sql*Plus。您可以使用预定义的位置变量变量从命令行将值传递到脚本中,如下所示:
define tableNm = &1
select * from &tableNm;
...然后像这样调用sqlplus:
sqlplus user/pwd@server @myscript.sql customers2008
如果未在命令行中传入值,系统将提示脚本调用者输入值。
请参阅Dave Costa在下面的答案,了解绑定和替换变量之间的差异。
答案 1 :(得分:8)
尝试添加一些解释:
您尝试使用的方法称为绑定变量。绑定变量在Oracle SQL中由冒号后跟标识符标识。绑定变量的目的是在解析SQL语句时不需要知道它的值;语句可以解析一次,然后执行多次,并使用绑定到变量的不同值。
为了解析SQL语句,必须知道所涉及的表名和列名。因此,表名不能用绑定变量表示,因为在解析时不会知道该值。
如果你只是通过SQLPlus执行SQL和内联PL / SQl,那么替换变量是处理这个问题的一种简单方法,正如史蒂夫解释的那样。当SQLPlus客户端读取命令时,替换变量将替换为其值,然后甚至将其发送到Oracle进行解析。
答案 2 :(得分:7)
你必须做这样的事情:
EXECUTE IMMEDIATE 'select * from' || tableNm;
这是因为Oracle不允许表(或任何其他对象名)的绑定变量。
EXECUTE IMMEDIATE方法存在重大安全隐患:当tableNm值由用户提供时,您可以对SQL injection攻击持开放态度。
答案 3 :(得分:6)
SQL> select * from &table_name;
Enter value for table_name: dual
old 1: select * from &table_name
new 1: select * from dual
D
-
X