将多个变量传递到PL/SQL存储过程中的WHERE条件

将多个变量传递到PL/SQL存储过程中的WHERE条件,sql,stored-procedures,plsql,Sql,Stored Procedures,Plsql,传递参数时执行此代码块时出现问题。参数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; 执行代码如

传递参数时执行此代码块时出现问题。参数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;
/
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;
我希望执行WHERE条件,如下所示:

where column_name in ('xyz','ran','dom');
但执行时将xyz、ran、dom视为字符串本身


有什么方法可以实现吗?

您可以将字符串分解出来,或者最简单的方法是使用INSTR

rf := ',' || rf || ',';

SELECT
    COUNT(*)
INTO
    counter
FROM
    test_pl_imp
WHERE
    INSTR(rf, ',' || column_name || ',') > 0;
如果您可以选择稍微重新设计它,我认为将一个字符串数组转换成一个表,这样您就可以加入test_pl_imp,这将是一个更干净的设计

这可以通过以下方式实现:

declare 
inparam varchar2(20) := 'xyz,ran,dom';
begin
goku.test_pl(inparam);
end;
/
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;
你可以做:

将存储的过程查询转换为动态查询,并将值作为“abc等”传递 实现一个split函数,将字符串拆分为临时表,并对其进行连接/查询。 你可以用INSTR,但有个窍门。 我已经写了一个拆分函数,我在那里工作,它非常适合这样的东西

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不够了解,很抱歉。。。我认为+符号应该是| |,但我想你明白了。

如果你将参数声明为单个stringvarchar,那么它将被视为唯一的字符串。
您可以尝试拆分参数:

您可以拆分输入字符串并使用临时表或表对象。这将允许优化器在列上使用索引。出于安全和性能原因,不要使用不带绑定的动态SQL

下面是一个表对象的示例。设置10g,因为它使用:


当仅提供MyString作为变量时,INSTR可能会遇到MyString和MyStringTest之类的问题。但是为了绕过它,你可以用一个特殊的字符和变量填充原始值,这样它就可以查找;MyString;相反我以前也玩过这个把戏。接近。。。您还需要为列表中的第一个值填充开头+1无论如何。干得好啊,你又是对的——我忘了如果你只搜索yz会发生什么。@Chris。。非常感谢你的帮助!非常好的“技巧”要记住。像奇迹一样工作!!只是一个疑问:您能告诉我如何在WHERE子句pl/sql中使用可变长度的数组吗?