将查询结果插入到由变量命名的表中

时间:2013-08-21 17:45:53

标签: sql oracle variables

我有一个存储过程,它运行许多查询并获得它存储在变量中的很多值。我希望此过程能够将查询结果插入到用户给出的表中。我会将给定的表名存储为varchar参数但是如何插入此表?

在编译时,Oracle表示该表不存在。

2 个答案:

答案 0 :(得分:5)

据推测,它告诉你一个你正在使用的变量名称的表格不存在,当然它不会。实际表格在编译时可能存在也可能不存在;因为它很灵活,所以假设它可能不安全可能更安全。无论哪种方式,你都不知道它会是什么,因此你需要使用动态SQL来实现这一目标。

正如在另一个答案的评论中所提到的,你必须小心SQL注入。通常,您希望在动态SQL中使用绑定变量,但不能对对象名称使用绑定,因此必须将其连接起来。希望你使用11g,其中包括dbms_assert包。

这是一个简单的例子:

create or replace procedure p42 (table_name varchar2) as
begin
  execute immediate 'insert into '
    || dbms_assert.qualified_sql_name(table_name)
    || ' select * from dual';
end;
/

然后我可以在程序已经存在后创建一个表,并成功调用该过程:

create table t42 (dummy varchar2(1));

exec p42('t42');

select * from t42;

DUMMY
-----
X     

您的真实查询显然会更复杂,并且应该将绑定变量用于您传入的目标表名称的任何过滤器值。


dbms_assert调用的优点是,如果传入非法内容,并且传递了令人讨厌的内容,则会出错:

exec p42('t42 select ''Y'' from dual union all');

ORA-44004: invalid qualified SQL name
ORA-06512: at "SYS.DBMS_ASSERT", line 207
ORA-06512: at "STACKOVERFLOW.P42", line 3
ORA-06512: at line 1

如果该过程简单地连接传递的值:

  execute immediate 'insert into ' || table_name || ' select * from dual';

...然后同一个调用将在表中插入两行:

exec p42('t42 select ''Y'' from dual union all');

select * from t42;

DUMMY
-----
Y     
X

如果数据完整性对您来说非常重要,那么需要担心的是。如果您无法使用dbms_assert,那么您可以尝试检查传递的名称是否实际存在于all_tables中,并且不包含union等任何内容,但是确认更安全你不会想到所有可能的攻击,让内置函数为你做出艰苦的工作。

答案 1 :(得分:0)

尝试这样的事情:

exec ('insert into ' + @tblname + ' (col) values (123)')