PLSQL 将数据从存储在 varchar2 中的 csv 列表移动到整数集合

PLSQL move data from csv list stored in varchar2 to a collection of integers

甲骨文 Express 11G R2: 在 PLSQL 中,我有一个包含 CSV 值列表的 varchar2,如下所示:

vList:='1212,3232,3232,4343,54545,65654,65665,65654,788787'

我想将它们移动到一个集合中,所以我创建了一个新类型:

CREATE TYPE INTEGER_TT AS TABLE OF INTEGER;

然后声明我的变量:

my_list INTEGER_TT;

用包含 CSV 的 varchar2 中的值填充 "my_list" 的最快方法是什么(就处理器时间而言,而不是执行时间)?

这是我当前的代码,查询本身运行大约需要 0.01 秒,加上 "bulk collect into" 大约需要 6 秒,列表包含大约 500 个值。

select regexp_substr( vList,'[^,]+', 1, level) intID 
bulk collect into my_list
from dual connect by regexp_substr(vList, '[^,]+', 1, level) is not null;

有比我上面的代码更好的选择吗?

性能会因平台、配置等而异,因此很难给出明确的答案。正则表达式的 0.1s 似乎很多,增加到 6s 来填充一个集合似乎过多。

由于您的字符串仅由数字组成,您可以尝试使用 XMLTable 的技巧:

select to_number(column_value)
bulk collect into my_list
from xmltable(vList);

这会将您的 CSV 列表作为 an XQuery expression 传递,并将其解释为 XQuery 序列。虽然这只适用于数字,但您不能将此方法用于字符串。

用随机整数生成的相同 500 元素列表比较方法的样本时间:

set serveroutput on
declare
  my_list INTEGER_TT;
  vList varchar2(32767);
  vTime pls_integer;
begin
  -- create list of 500 random integers
  vTime := dbms_utility.get_time;
  select listagg(trunc(dbms_random.value(1, 10000)), ',')
    within group (order by null)
  into vList
  from dual
  connect by level <= 500;
  dbms_output.put_line('Creating list took ' || (dbms_utility.get_time - vTime));

  -- original regex approach
  vTime := dbms_utility.get_time;
  select regexp_substr( vList,'[^,]+', 1, level) intID 
  bulk collect into my_list
  from dual connect by regexp_substr(vList, '[^,]+', 1, level) is not null;
  dbms_output.put_line('Regex took ' || (dbms_utility.get_time - vTime));

  -- XMLTable approach
  vTime := dbms_utility.get_time;
  select to_number(column_value)
  bulk collect into my_list
  from xmltable(vList);
  dbms_output.put_line('XMLTable took ' || (dbms_utility.get_time - vTime));
end;
/

获取以下次数,以百分之一秒为单位:

Creating list took 2
Regex took 188
XMLTable took 3

您可能会因为不同的结果,或不同程度的差异...


如果您这样做是为了将集合用作 SQL 查询中的数据源 - 这是可能的,因为它是架构级集合类型 - 您可以跳过该步骤。如果您使用的是 table(my_list),则可以直接参考 xmltable(vList)。您可以完全避免 PL/SQL,具体取决于您在做什么;尽管无论如何您都可以使用 CTE 做到这一点。