甲骨文 SQL: select regexp_substr, "into clause is expected"

Oracle SQL: select regexp_substr, "into clause is expected"

我正在尝试使用 regexp_substr 拆分以逗号分隔的字符串,但出现 "into clause is expected" 错误:

 select regexp_substr(improv,'[^,]+', 1, level) from dual
 connect by regexp_substr(improv, '[^,]+', 1, level) is not null;

"improv"是一个varchar(100)变量,而我运行上面的语句在一个PLSQL块里面。

在PL/SQL你需要输出SQl查询INTO一个变量。

但是,由于此查询将生成多行,您可能希望使用 BULK COLLECT INTO 而不仅仅是 INTO 并将输出放入用户定义的集合或 VARRAY(其中 SYS.ODCIVARCHAR2LIST 是一个例子。注意:您不能将 MEMBER OF 运算符与 VARRAY 一起使用:

DECLARE
  list_of_improvs SYS.ODCIVARCHAR2LIST;
BEGIN
  SELECT regexp_substr(improv,'[^,]+', 1, level)
  BULK COLLECT INTO list_of_improvs
  FROM   DUAL
  CONNECT BY regexp_substr(improv, '[^,]+', 1, level) is not null;
END;
/

更新:

回应您的评论 - 您可以像这样使用它(虽然不清楚您要实现什么,所以我只是将您的代码放入一个片段中,而没有试图弄清楚您打算做什么) :

DECLARE
  list_of_improvs SYS.ODCIVARCHAR2LIST;
BEGIN
  SELECT regexp_substr(improv,'[^,]+', 1, level)
  BULK COLLECT INTO list_of_improvs
  FROM   DUAL
  CONNECT BY regexp_substr(improv, '[^,]+', 1, level) is not null;

  FOR i IN 1 .. list_of_improvs.COUNT LOOP
    DBMS_OUTPUT.PUT_LINE( improvs(i) );
  END LOOP;

  update line_cap
    set   cap_up = list_of_improvs(1)
    where id IN ( SELECT Column_Value
                  FROM TABLE( list_of_improvs ) );
END;
/

您不能将 IN 直接用于集合或 VARRAY,需要在嵌套查询中使用 TABLE() 集合表达式来获取值。

如果您使用的是用户定义的 SQL 集合 - 即使用如下语句定义:

CREATE TYPE StringList IS TABLE OF VARCHAR2(4000);

然后可以使用MEMBER OF运算符:

DECLARE
  list_of_improvs StringList;
BEGIN
  -- as above

  update line_cap
    set   cap_up = list_of_improvs(1)
    where id MEMBER OF list_of_improvs;
END;
/

但是您不能将 MEMBER OF 运算符与 VARRAY 一起使用(如 SYS.ODCIVARCHAR2LIST)。

但是,您不需要 PL/SQL(并消除 PL/SQL 和 SQL 执行范围之间昂贵的上下文切换)并且可以只使用 MERGE 语句类似于:

MERGE INTO line_cap dst
USING (
  SELECT MIN( value ) KEEP ( DENSE_RANK FIRST ORDER BY ROWNUM ) OVER () AS first_value,
         value
  FROM   (
    SELECT regexp_substr(improv,'[^,]+', 1, level) AS value
    FROM   DUAL
    CONNECT BY regexp_substr(improv, '[^,]+', 1, level) is not null
  )
) src
ON ( src.value = dst.id )
WHEN MATCHED THEN
  UPDATE
    SET cap_up = first_value;

我把它放在这里而不是对 MT0 的回答的评论,因为评论不适用于格式化。无论如何,这是一个完整的示例,它使用 MT0 的答案来加载一个数组,然后循环遍历它以显示内容。这将向您展示如何访问列表的内容。感谢 MT0 为您提供原始问题的答案。

DECLARE
  list_of_improvs SYS.ODCIVARCHAR2LIST;
  i number;
BEGIN
  SELECT regexp_substr('1,2,3,4,5','(.*?)(,|$)', 1, level, NULL, 1)
  BULK COLLECT INTO list_of_improvs
  FROM   dual
  CONNECT BY level <= regexp_count('1,2,3,4,5', ',') + 1;

  i := list_of_improvs.FIRST;  -- Get first element of array
  while i is not null LOOP
    DBMS_OUTPUT.PUT_LINE(list_of_improvs(i));
    i := list_of_improvs.NEXT(i);  -- Get next element of array
  END LOOP;
END;
/