在循环中立即执行获取 table 数据
Getting table data with execute immediate in a loop
我正在尝试从表中提取数据。多个表的名称可以作为逗号分隔值(如 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
我哪里做错了?
您只能绑定变量,不能绑定对象名称。绑定替换是在执行查询时完成的,而不是在解析查询时完成的。必须在解析时知道对象名称。
您必须将架构和 table 名称连接到查询中:
...
begin
p_statement := 'select * from ';
...
execute immediate p_statement || p_schema_name ||'.'|| foo.txt;
end loop;
end;
当然,现在有可能 SQL injection, so you need to sanitise the inputs. You can check if they are valid names, or check the extracted tables exist in the specified schema before trying to execute the query. You might find the DBMS_ASSERT package 有用。
虽然您的查询目前不会真正执行; from the documentation:
If dynamic_sql_statement is a SELECT statement, and you omit both into_clause and bulk_collect_into_clause, then execute_immediate_statement never executes.
您需要将您的数据 select 转换成某种东西,如果可以传入的 table 具有不同的结构,这将很棘手。如果您打算将查询的数据写入文件并且不知道结构,那么您需要使用 the DBMS_SQL package 而不是 execute immediate
.
Table 名称和列名称不能作为绑定变量传递给立即执行语句!
而是将它们用作变量并将它们连接起来。
但是另一个错误是您缺少一个 INTO 子句,用于处理 SELECT 语句的 Execute immediate 语句,正如其他贡献者所说。
谢谢,
B
根据您的问题,您将如何处理来自 PLSQL 的 SELECT * 查询的输出。我猜你要么需要有一个 ref 游标来使用它。另外,根据您的代码,如果您遍历多个 tables,输出将始终被下一个覆盖,因此您将仅获得最后一个查询输出。
所以对于这个假脱机文件中的输出并迭代到下一个 table.
希望此信息对您有所帮助。
我正在尝试从表中提取数据。多个表的名称可以作为逗号分隔值(如 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
我哪里做错了?
您只能绑定变量,不能绑定对象名称。绑定替换是在执行查询时完成的,而不是在解析查询时完成的。必须在解析时知道对象名称。
您必须将架构和 table 名称连接到查询中:
...
begin
p_statement := 'select * from ';
...
execute immediate p_statement || p_schema_name ||'.'|| foo.txt;
end loop;
end;
当然,现在有可能 SQL injection, so you need to sanitise the inputs. You can check if they are valid names, or check the extracted tables exist in the specified schema before trying to execute the query. You might find the DBMS_ASSERT package 有用。
虽然您的查询目前不会真正执行; from the documentation:
If dynamic_sql_statement is a SELECT statement, and you omit both into_clause and bulk_collect_into_clause, then execute_immediate_statement never executes.
您需要将您的数据 select 转换成某种东西,如果可以传入的 table 具有不同的结构,这将很棘手。如果您打算将查询的数据写入文件并且不知道结构,那么您需要使用 the DBMS_SQL package 而不是 execute immediate
.
Table 名称和列名称不能作为绑定变量传递给立即执行语句!
而是将它们用作变量并将它们连接起来。
但是另一个错误是您缺少一个 INTO 子句,用于处理 SELECT 语句的 Execute immediate 语句,正如其他贡献者所说。
谢谢, B
根据您的问题,您将如何处理来自 PLSQL 的 SELECT * 查询的输出。我猜你要么需要有一个 ref 游标来使用它。另外,根据您的代码,如果您遍历多个 tables,输出将始终被下一个覆盖,因此您将仅获得最后一个查询输出。 所以对于这个假脱机文件中的输出并迭代到下一个 table.
希望此信息对您有所帮助。