使用dbms_utility.comma_to_table获取"xx.yy'附近的逗号分隔列表'无效"

kal*_*uva 2 sql oracle plsql string-split

我有这样的字符串:str:='ac_Abc.88,ac_Abc.99,ac_Abc.77'.我需要在用逗号(,)分割后得到第一个元素.所以即时使用像这样:

str VARCHAR2(500);
dbms_utility.comma_to_table
      ( list   => regexp_replace(str,'(^|,)','\1')
      , tablen => l_count
      , tab    => l_array
     ); 
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

ORA-20001: comma-separated list invalid near bc.88
ORA-06512: at "SYS.DBMS_UTILITY", line 239
ORA-06512: at "SYS.DBMS_UTILITY", line 272
Run Code Online (Sandbox Code Playgroud)

但如果我有这样的字符串,str:='ac_Abc88,ac_Abc99,ac_Abc77',同样的方法工作正常并给我预期的结果.

所以我想有些东西需要纠正才能考虑"." 作为常规角色.你能建议我怎么解决这个问题.

Lal*_*r B 12

请参见如何将逗号分隔的字符串拆分为行

1. REGEXP_SUBSTR方法

SQL> WITH DATA AS(
  2  SELECT 'ac_Abc.88,ac_Abc.99,ac_Abc.77' str FROM dual)
  3  SELECT regexp_substr(str,'[^,]+',1,level) str
  4  FROM DATA
  5    CONNECT BY regexp_substr(str, '[^,]+', 1, level) IS NOT NULL
  6  /

STR
-----------------------------
ac_Abc.88
ac_Abc.99
ac_Abc.77

SQL>
Run Code Online (Sandbox Code Playgroud)

2. XML方法

SQL> SELECT EXTRACT (VALUE (d), '//row/text()').getstringval () str
  2  FROM
  3    (SELECT XMLTYPE ( '<rows><row>'
  4      || REPLACE ('ac_Abc.88,ac_Abc.99,ac_Abc.77', ',', '</row><row>')
  5      || '</row></rows>' ) AS xmlval
  6    FROM DUAL
  7    ) x,
  8    TABLE (XMLSEQUENCE (EXTRACT (x.xmlval, '/rows/row'))) d
  9  /

STR
--------------------
ac_Abc.88
ac_Abc.99
ac_Abc.77
Run Code Online (Sandbox Code Playgroud)

3.表功能

SQL> CREATE TYPE test_type
  2  AS
  3    TABLE OF VARCHAR2(100)
  4  /

Type created.

SQL>
SQL> CREATE OR REPLACE
  2  FUNCTION comma_to_table(
  3      p_list IN VARCHAR2)
  4    RETURN test_type
  5  AS
  6    l_string VARCHAR2(32767) := p_list || ',';
  7    l_comma_index PLS_INTEGER;
  8    l_index PLS_INTEGER := 1;
  9    l_tab test_type     := test_type();
 10  BEGIN
 11    LOOP
 12      l_comma_index := INSTR(l_string, ',', l_index);
 13      EXIT
 14    WHEN l_comma_index = 0;
 15      l_tab.EXTEND;
 16      l_tab(l_tab.COUNT) := SUBSTR(l_string, l_index, l_comma_index - l_index);
 17      l_index            := l_comma_index                           + 1;
 18    END LOOP;
 19    RETURN l_tab;
 20  END comma_to_table;
 21  /

Function created.

SQL> sho err
No errors.
SQL>
SQL> SELECT * FROM TABLE(comma_to_table('ac_Abc.88,ac_Abc.99,ac_Abc.77'))
  2  /

COLUMN_VALUE
--------------------------------------------------------------------------------
ac_Abc.88
ac_Abc.99
ac_Abc.77

SQL>
Run Code Online (Sandbox Code Playgroud)

4.流水线功能

SQL> CREATE OR REPLACE
  2    FUNCTION comma_to_table(
  3        p_list IN VARCHAR2)
  4      RETURN test_type PIPELINED
  5    AS
  6      l_string LONG := p_list || ',';
  7      l_comma_index PLS_INTEGER;
  8      l_index PLS_INTEGER := 1;
  9    BEGIN
 10      LOOP
 11        l_comma_index := INSTR(l_string, ',', l_index);
 12        EXIT
 13      WHEN l_comma_index = 0;
 14        PIPE ROW ( SUBSTR(l_string, l_index, l_comma_index - l_index) );
 15        l_index := l_comma_index                           + 1;
 16      END LOOP;
 17      RETURN;
 18    END comma_to_table;
 19    /

Function created.

SQL> sho err
No errors.
SQL>
SQL> SELECT * FROM TABLE(comma_to_table('ac_Abc.88,ac_Abc.99,ac_Abc.77'))
  2  /

COLUMN_VALUE
--------------------------------------------------------------------------------
ac_Abc.88
ac_Abc.99
ac_Abc.77
Run Code Online (Sandbox Code Playgroud)


nop*_*svk 5

这是因为(Oracle文档参考

COMMA_TO_TABLE过程

这些过程将以逗号分隔的名称列表转换为PL / SQL名称表。第二个版本支持完全限定的属性名称。

此处提到的“名称”是有效的Oracle(数据库对象)标识符,所有命名规则都适用于该标识符。ac_Abc.88名称无效,因为在Oracle中您不能使用以数字开头的标识符。

要解决解析逗号分隔值的字符串的问题,请使用以下Lalit Kumar解决方案。