在循环中立即执行获取表数据
Posted
技术标签:
【中文标题】在循环中立即执行获取表数据【英文标题】:Getting table data with execute immediate in a loop 【发布时间】:2016-06-07 11:16:22 【问题描述】:我正在尝试从表中提取数据。多个表的名称可以以逗号分隔值(如 a、b、c)的形式给出,并且基于此我需要将数据提取到文件中。下面是通过 SQL*Plus 运行的代码:
declare
p_schema_name varchar2(1000) := '&1';
p_table_names varchar2(4000) := '&2';
p_statement varchar2(4000);
begin
p_statement := 'select * from :x'||'.'||':y';
for foo in (
select
regexp_substr (replace(p_table_names, ' ', ''), '[^,]+', 1, level) as txt
from dual
connect by
regexp_substr (replace(p_table_names, ' ', ''), '[^,]+', 1, level) is not null)
loop
execute immediate p_statement using p_schema_name, foo.txt;
end loop;
end;
当我执行此脚本时,我收到以下错误:
ORA-00903: invalid table name
ORA-06512: at line 14
我哪里做错了?
【问题讨论】:
【参考方案1】:您只能绑定变量,不能绑定对象名称。绑定替换是在执行查询时完成的,而不是在解析时完成的。解析时必须知道对象名称。
您必须将架构和表名连接到查询中:
...
begin
p_statement := 'select * from ';
...
execute immediate p_statement || p_schema_name ||'.'|| foo.txt;
end loop;
end;
当然,现在SQL injection 具有潜力,因此您需要清理输入。您可以检查它们是否是有效名称,或者在尝试执行查询之前检查提取的表是否存在于指定的架构中。您可能会发现 the DBMS_ASSERT package 很有用。
虽然您的查询目前不会真正执行; from the documentation:
如果 dynamic_sql_statement 是一个 SELECT 语句,并且您省略了 into_clause 和 bulk_collect_into_clause,那么 execute_immediate_statement 永远不会执行.
您需要将您的数据选择到某个东西中,如果可以传入的表具有不同的结构,这将是一件棘手的事情。如果您打算将查询的数据写入文件并且不知道结构,那么您需要使用the DBMS_SQL package 而不是execute immediate
。
【讨论】:
【参考方案2】:表名和列名不能作为绑定变量传递给立即执行语句!
而是将它们用作变量并将它们连接起来。
但是另一个错误是您缺少执行立即语句的 INTO 子句来处理其他贡献者所说的 SELECT 语句。
谢谢, 乙
【讨论】:
【参考方案3】:根据您的问题,您将如何处理来自 PLSQL 的 SELECT * 查询的输出。我猜你要么需要一个参考光标才能使用它。同样根据您的代码,如果您遍历多个表,则输出将始终被下一个表覆盖,因此您将仅获得最后一个查询输出。 因此,对于这个假脱机,输出一个文件并迭代到下一个表。
希望这些信息对您有所帮助。
【讨论】:
以上是关于在循环中立即执行获取表数据的主要内容,如果未能解决你的问题,请参考以下文章