如何在 Oracle 过程 where 子句中使用 listagg 参数

How to use listagg parameter in Oracle procedure where clause

我使用 LISTAGG 将一系列 ID 分组。 下面是一个返回值的例子-

A     1,2,3,4,5    PROC.ABC
B     6,7,8        PROC.ABC
C     2,3,4        PROC.DEF

然后我尝试使用游标并将每个值传递给以下过程:

PROCEDURE abc(id_list IN VARCHAR2) IS
BEGIN
  UPDATE table_a SET flag = 1 WHERE id IN (id_list);
END;

这会出错(“无效数字”错误),因为 id_list 被插入为

'1,2,3,4,5'

,不是

1,2,3,4,5

。我怎样才能让它工作?如果可能,我宁愿不使用动态 SQL。

如果您的数据库中安装了 APEX,则可以使用 APEX_STRING.SPLIT 函数以逗号分隔字符串。如果您知道 id_list 总是数字,您也可以使用 APEX_STRING.SPLIT_NUMBERS

PROCEDURE abc (id_list IN VARCHAR2)
IS
BEGIN
    UPDATE table_a
       SET flag = 1
     WHERE id IN (SELECT * FROM TABLE (apex_string.split (id_list, ',')));
END;

首先,您需要创建一个 returns 值列表的函数。

FUNCTION TVF_SPLIT (expression CLOB, delimiter CHAR) RETURN sys.ODCIVARCHAR2LIST
AS
v_TYPE_TABLE_SEPRATOR sys.ODCIVARCHAR2LIST :=sys.ODCIVARCHAR2LIST();
v_xml_data CLOB;

BEGIN

v_xml_data := '<r><n>' || replace(expression,delimiter,'</n><n>') || '</n></r>';

SELECT * BULK COLLECT INTO v_TYPE_TABLE_SEPRATOR FROM
    (
        SELECT * FROM
            XMLTABLE ( '/r/*' 
            PASSING xmltype(v_xml_data) 
            COLUMNS 
                r VARCHAR2(4000) PATH '/n' 
            ) xmlt
    );

RETURN v_TYPE_TABLE_SEPRATOR;
END;

Select * from table(TVF_SPLIT('1,2,3,4,5',','));

不要使用listagg;创建集合类型。

create or replace type t_vchar_tab as table of integer

然后在query中替换listagg-

CAST(COLLECT(id) AS t_vchar_tab) as id_list

那么程序应该引用 MEMBER

的集合 w/use
PROCEDURE abc(id_list t_vchar_tab) IS
BEGIN
  UPDATE table_a SET flag = 1 WHERE id MEMBER OF id_list;
END;