如何在 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;
我使用 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/usePROCEDURE abc(id_list t_vchar_tab) IS
BEGIN
UPDATE table_a SET flag = 1 WHERE id MEMBER OF id_list;
END;