PL / SQL重写用“IN”子句级联查询(PL/SQL rewrite concatenated

2019-08-16 23:50发布

目前,我在下面的语句我的PL / SQL代码:

-- vList looks like '1,2,3,4'     
vStatement := 'SELECT NAME FROM T_USER WHERE ID IN ( ' || vList || ' ) '; 
Execute Immediate vStatement BULK COLLECT INTO tNames;

我认为,串联查询,如果不好的做法,所以我想使这个查询,而无需使用蜇伤。 什么是重写这个方法是什么?

PS也许这里的人能够指出为什么查询的串联是不好的,因为我没有足够的理由证明,这种风格是坏的。

Answer 1:

我的猜测是,你采取了一些步骤之前获得VLIST的ID为分隔字符串(你不说VLIST如何填充)。 为什么不继续作为一个查询?

begin
...
select name
bulk collect into tNames
from t_user
where id in (select id from some_table where ...);
...

上下文时多次运行可能是痛苦的,但对我来说最糟糕的是,你是盲目地接受参数输入是数字的列表,当它可以是任何东西真的开关。 这可能(天真)是“1,2,X”,你会得到一个运行时错误“无效号码”。 更糟的是,它可能是一个SQL注入攻击。 它一般是不好的做法(动态SQL的确有它的地方),但肯定你不是如何使用它。

尝试是这样的:

create or replace type t_num_tab as table of number;

create or replace procedure test_proc(i_list in t_num_tab) as
  type t_name_tab is table of varchar2(100);
  l_names t_name_tab;
begin
  -- get names
  select name
  bulk collect into l_names
  from user_table
  where id in (select * from table(i_list));

  -- do something with l_names
  dbms_output.put_line('Name count: ' || l_names.count);

end;

如果你需要的东西比数字的列表比较复杂,您可以创建一个对象类型。



Answer 2:

这不仅仅是因为级联是缓慢的。 这是在PLSQL动态查询是很慢的。 下面是如何和为什么做到这一点两者很好的书面记录:

问汤姆:我怎样才能做一个变量“列表中的”



文章来源: PL/SQL rewrite concatenated query with 'IN' clause