1

目前,我的 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;

我认为如果不好的做法连接查询,所以我想在不使用 stings 的情况下进行此查询。重写这个的方法是什么?

PS也许这里的人可以指出为什么查询连接不好,因为我没有足够的理由证明这种风格不好。

4

2 回答 2

2

我的猜测是您之前采取了一些步骤将 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',你会得到一个运行时错误“invalid number”。或者更糟的是,它可能是 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;

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

于 2013-02-15T14:43:16.747 回答
1

不仅仅是连接很慢。plsql 中的动态查询真的很慢。这是一个很好的关于如何以及为什么这样做的文章:

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

于 2013-02-15T15:08:31.280 回答