传递参数时执行此代码块时出现问题。参数 rf 是要输入WHERE子句的变量列表。要输入的变量数量不是静态的。
create or replace
procedure test_pl(rf in varchar2)
IS
counter number;
BEGIN
select count(*) into counter from test_pl_imp where column_name in (rf);
dbms_output.put_line(counter);
END;
执行代码如下:
declare
inparam varchar2(20) := 'xyz,ran,dom';
begin
goku.test_pl(inparam);
end;
/
我希望WHERE条件执行如下:
where column_name in ('xyz','ran','dom');
但它会以xyz,ran,dom
作为字符串本身来执行。
有没有办法实现它?
答案 0 :(得分:5)
你可以将字符串分解出来,或者最简单的方法是使用INSTR。
rf := ',' || rf || ',';
SELECT
COUNT(*)
INTO
counter
FROM
test_pl_imp
WHERE
INSTR(rf, ',' || column_name || ',') > 0;
如果您可以选择稍微重新设计,我认为采用字符串数组并将其转换为TABLE以便您可以加入test_pl_imp将是一种更简洁的设计。
这可以按如下方式完成:
DECLARE
l_array goku.t_type := goku.t_type();
BEGIN
l_array.extend(3);
l_array(1) := 'xzy';
l_array(2) := 'abc';
l_array(2) := '123';
goku.test_pl(l_array);
END;
然后您的软件包规范将包括以下内容,因为您希望上述调用的类型和过程是公开的:
CREATE OR REPLACE PACKAGE goku
TYPE r_type IS RECORD (
search_term VARCHAR2 (30)
);
TYPE t_type IS TABLE OF r_type;
PROCEDURE test_pl(l_array IN t_type);
END goku;
你的包裹体如下:
CREATE OR REPLACE PACKAGE BODY goku
PROCEDURE test_pl(l_array IN t_type) IS
v_counter NUMBER;
BEGIN
SELECT
COUNT(tpi.*)
INTO
v_counter
FROM
test_pl_imp tpi
, TABLE( CAST(l_array as r_type)) la
WHERE
tpi.column_name = la.search_term;
DBMS_OUTPUT.PUT_LINE('Count :' || v_counter);
END;
END goku;
答案 1 :(得分:1)
你可以这样做:
我已经编写了一个分割功能,我可以在这里工作,对于像这样的东西来说效果非常好。
INSTR技巧:您当前正在将逗号作为分隔符传递,这就是我在'技巧'中使用的,但您也可以使用分号。基本上,假设你想找到'abc,def'中的所有内容。你填充你的字符串使它看起来像',abc,def,'然后填充搜索的值,使它看起来像',abc,'。这样,找不到'abctest'和'testabc',而找到'abc'。
SELECT
COUNT(*)
INTO
counter
FROM
test_pl_imp
WHERE
INSTR(',' + rf + ',', ',' + column_name + ',') > 0;
很抱歉,如果我不太了解PL / SQL ......我认为需要的是+符号,但我认为你明白这一点。
答案 2 :(得分:1)
您将参数声明为单个字符串(varchar),然后将其视为唯一字符串。 您可以尝试拆分参数:http://www.codeproject.com/Articles/7938/SQL-User-Defined-Function-to-Parse-a-Delimited-Str
答案 3 :(得分:1)
您可以拆分输入字符串,并使用临时表或表对象。这将允许优化器在列上使用索引。不要在没有绑定的情况下使用动态SQL(出于安全性和性能原因)。
这是一个表对象的示例。设置(10g,因为它使用REGEXP_SUBSTR):
CREATE TYPE tab_varchar2 IS TABLE OF VARCHAR2(100);-- longest string
/
CREATE OR REPLACE PROCEDURE test_pl(rf IN VARCHAR2) IS
lt tab_varchar2;
counter NUMBER;
BEGIN
-- split parameter
SELECT rtrim(regexp_substr(str, '[^,]*,', 1, level), ',')
BULK COLLECT INTO lt
FROM (SELECT rf || ',' str FROM dual)
CONNECT BY level <= length(str) - length(replace(str, ',', ''));
-- your query
SELECT count(*)
INTO counter
FROM test_pl_imp
WHERE column_name IN (SELECT column_value FROM TABLE(lt));
dbms_output.put_line(counter);
END;
/