在动态 sql 中使用集合
Posted
技术标签:
【中文标题】在动态 sql 中使用集合【英文标题】:Using collection inside dynamic sql 【发布时间】:2017-02-08 08:13:18 【问题描述】:我正在尝试将 dbms_sql.number_table 从一个过程传递到另一个过程,然后在动态 plsql 块中使用它。但是下面的代码会抛出错误:
错误(6,17):PLS-00306:调用“||”时参数的数量或类型错误
create or replace
procedure proc1( v_in_table_name varchar2,
v_in_column_name varchar2,
v_in dbms_sql.number_table)
as
plsql_block varchar2(4000);
begin
plsql_block:='declare
begin
FORALL INDX IN 1 ..'||v_in.count||' SAVE EXCEPTIONS
UPDATE '||v_in_table_name||'
Set '||v_in_column_name||'=123 WHERE col2='||v_in||'(INDX)||;
end';
execute immediate plsql_block;
end proc1;
【问题讨论】:
【参考方案1】:您应该进行两项更改:
首先(及其错误情况)是当您将字符串与集合连接时。
如果要将集合发送到 pl/sql 块中,则应使用参数。
其次,您应该在动态 pl\sql 的末尾添加;
:
create or replace
procedure proc1(v_in dbms_sql.number_table)
as
plsql_block varchar2(4000);
begin
plsql_block:='declare
l_collect dbms_sql.number_table := :number_table ;
begin
FORALL INDX IN 1 ..'||v_in.count||' SAVE EXCEPTIONS
UPDATE table_name
Set col1=123 WHERE col2=l_collect(INDX);
end;';
execute immediate plsql_block using v_in;
end proc1;
但在所有的变化之后我想问:你真的需要使用动态 pl\sql 吗?
【讨论】:
不确定你在哪里试过因为我有 oracle 11gR2,它给了我这个错误PLS-00457: expressions have to be of SQL types
。我会说再试一次并发布工作版本
编译时出现此错误 Error(13,41): PLS-00457: 表达式必须是 SQL 类型【参考方案2】:
不需要使用动态块。我也不认为它也可以工作。你可以这样用;
create or replace
procedure proc1(v_in dbms_sql.number_table)
as
plsql_block varchar2(4000);
l_collect dbms_sql.number_table;
begin
l_collect := v_in;
FORALL INDX IN 1 ..l_collect.count SAVE EXCEPTIONS
UPDATE table_name
Set col1=123
WHERE col2=l_collect(INDX);
commit;
end proc1;
执行:
SQL> DECLARE
var DBMS_SQL.number_table;
BEGIN
var (1) := 1;
var (2) := 2;
var (3) := 3;
proc1 (var);
END;
/
PL/SQL procedure successfully completed.
编辑:根据您的编辑,代码如下:
create or replace procedure proc1 (v_in_table_name varchar2,
v_in_column_name varchar2,
v_in dbms_sql.number_table)
as
plsql_block varchar2 (4000);
begin
plsql_block := q'[ FORALL INDX IN 1 ..v_in.count SAVE EXCEPTIONS
UPDATE :table_name
Set :col1=123
WHERE col2=v_in(INDX)]';
execute immediate plsql_block using v_in_table_name, v_in_column_name;
commit;
end proc1;
【讨论】:
我正在动态 plsql 块中进行其他处理,所以我需要在动态块中进行所有处理。 您只是在循环集合内的数据。我也在做同样的事情。我只是将数据处理为一个变量并运行它。动态块的需要在这里没用 我的要求是需要使用动态块 您想使用动态 sql 实现什么。因为无论您想实现什么,都可以使用上述方法完成。 更新语句中的表名是动态的,因此是动态块以上是关于在动态 sql 中使用集合的主要内容,如果未能解决你的问题,请参考以下文章
MyBatis中动态sql的模糊搜索foreach实现In集合的用法
MyBatis中动态sql实现传递多个参数并使用if进行参数的判断和实现like模糊搜索以及foreach实现in集合