简体   繁体   English

从Oracle(> 11g)中的逗号分隔列表创建表-输入字符串限制为4000个字符

[英]Creating a table from a Comma Separated List in Oracle (> 11g) - Input string limit 4000 chars

I have an Oracle (11g) SP which takes a comma separated string of inputs (eg 'Cats, Dogs, Monkeys'). 我有一个Oracle(11g)SP,它以逗号分隔输入字符串(例如,“猫,狗,猴子”)。 The crux of the code is taken from Tony Andrews' blog and works as expected but it will not accept input strings greater than 4000 characters: 该代码的症结来自于Tony Andrews的博客,并且按预期工作,但是它不接受大于4000个字符的输入字符串:

PROCEDURE delimstring_to_table ( p_delimstring IN VARCHAR2
    , p_table OUT VARCHAR2_TABLE
    , p_nfields OUT INTEGER
    , p_delim IN VARCHAR2 DEFAULT ','
)
IS
    v_string VARCHAR2(32767) := p_delimstring;
    v_nfields PLS_INTEGER := 1;
    v_table VARCHAR2_TABLE;
    v_delimpos PLS_INTEGER := INSTR(p_delimstring, p_delim);
    v_delimlen PLS_INTEGER := LENGTH(p_delim);
BEGIN

  WHILE v_delimpos > 0
  LOOP
    v_table(v_nfields) := SUBSTR(v_string,1,v_delimpos-1);
    v_string := SUBSTR(v_string,v_delimpos+v_delimlen);
    v_nfields := v_nfields+1;
    v_delimpos := INSTR(v_string, p_delim);
  END LOOP;

  v_table(v_nfields) := v_string;
  p_table := v_table;
  p_nfields := v_nfields;

END delimstring_to_table;

Reference - Tony Andrews Blog 参考-Tony Andrews博客

The functions above are then used inside any relevant SPs within the package: 然后,可以在包内的任何相关SP内使用以上功能:

PROCEDURE Get_Animals(
                   p_Animals          IN       VARCHAR2 := NULL
                   , resultset_out    OUT      resultset_typ  
                   , error_out        OUT      VARCHAR2                                        
                   )
IS

BEGIN

    IF p_Animals IS NULL THEN
    OPEN resultset_out FOR
          SELECT /*+ ALL_ROWS */ * FROM ANIMALS ORDER BY NAME;
    ELSE
        OPEN resultset_out FOR
          SELECT * FROM ANIMALS where NAME in (SELECT * FROM TABLE  (Comma_To_Table(p_RICs)));         
END IF;

error_out := NULL;

EXCEPTION
WHEN OTHERS THEN
           error_out := 'Get_Animals() -> ' || SUBSTR(SQLERRM,1,200);

END Get_Animals; 

If the input string is > 4000 characters, I get the following error from the SP: 如果输入的字符串> 4000个字符,我从SP中收到以下错误:

ORA-00604: error occurred at recursive SQL level 1
ORA-01003: no statement parsed - GET_ANIMALS

I have two questions: 我有两个问题:

  1. Can I make the function work with input strings greater than 4000 characters? 我可以使函数使用大于4000个字符的输入字符串吗?
  2. Is there a more effective way of achieving the same result? 有没有更有效的方法来达到相同的结果?

Any help or suggestions would be much appreciated. 任何帮助或建议,将不胜感激。

  1. Can I make the function work with input strings greater than 4000 characters? 我可以使函数使用大于4000个字符的输入字符串吗? Yes, you can use for example CLOB 是的,您可以使用例如CLOB

  2. Is there a more effective way of achieving the same result? 有没有更有效的方法来达到相同的结果? I saw in the comments of the blog a good answer, which is about a recursive solution. 我在博客的评论中看到了一个很好的答案,这是一个递归解决方案。

just make some datatype changes for making it to work eg: 只需进行一些数据类型更改即可使其工作,例如:

  • change the varchar2_table type to CLOB 将varchar2_table类型更改为CLOB

     TYPE varchar2_table IS TABLE OF CLOB INDEX BY BINARY_INTEGER; 
  • change the VARCHAR2 datatype to CLOB in all p_delimstring occurences 在所有p_delimstring事件中将VARCHAR2数据类型更改为CLOB

  • change original SUBSTR functions to DBMS_LOB.SUBSTR (if you need more info about that: http://docs.oracle.com/cd/A91202_01/901_doc/appdev.901/a89852/dbms_23b.htm ) 将原始SUBSTR函数更改为DBMS_LOB.SUBSTR(如果您需要更多有关此信息,请访问: http : //docs.oracle.com/cd/A91202_01/901_doc/appdev.901/a89852/dbms_23b.htm

     CREATE OR REPLACE PACKAGE parse AS /* || Package of utility procedures for parsing delimited or fixed position strings into tables || of individual values, and vice versa. */ TYPE varchar2_table IS TABLE OF CLOB INDEX BY BINARY_INTEGER; PROCEDURE delimstring_to_table ( p_delimstring IN CLOB , p_table OUT varchar2_table , p_nfields OUT INTEGER , p_delim IN VARCHAR2 DEFAULT ',' ); PROCEDURE table_to_delimstring ( p_table IN varchar2_table , p_delimstring OUT CLOB , p_delim IN VARCHAR2 DEFAULT ',' ); END parse; / CREATE OR REPLACE PACKAGE BODY parse AS PROCEDURE delimstring_to_table ( p_delimstring IN CLOB , p_table OUT varchar2_table , p_nfields OUT INTEGER , p_delim IN VARCHAR2 DEFAULT ',' ) IS v_string CLOB := p_delimstring; v_nfields PLS_INTEGER := 1; v_table varchar2_table; v_delimpos PLS_INTEGER := INSTR(p_delimstring, p_delim); v_delimlen PLS_INTEGER := LENGTH(p_delim); BEGIN WHILE v_delimpos > 0 LOOP v_table(v_nfields) := DBMS_LOB.SUBSTR(v_string,1,v_delimpos-1); v_string := DBMS_LOB.SUBSTR(v_string,v_delimpos+v_delimlen); v_nfields := v_nfields+1; v_delimpos := INSTR(v_string, p_delim); END LOOP; v_table(v_nfields) := v_string; p_table := v_table; p_nfields := v_nfields; END delimstring_to_table; PROCEDURE table_to_delimstring ( p_table IN varchar2_table , p_delimstring OUT CLOB , p_delim IN VARCHAR2 DEFAULT ',' ) IS v_nfields PLS_INTEGER := p_table.COUNT; v_string CLOB; BEGIN FOR i IN 1..v_nfields LOOP v_string := v_string || p_table(i); IF i != v_nfields THEN v_string := v_string || p_delim; END IF; END LOOP; p_delimstring := v_string; END table_to_delimstring; END parse; / 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM