oracle-databasestored-proceduresoracle9i

comma separated value to loop working with Hardcoded value but not with parameter value


My main problem is : i want to pass comma separated string in to oracle 9i stored proc and inside it, i want to iterate through it and use each value in insert statements. Oracle 9i above version gives some internal function like regex_susbstr which can be used to implement this but with oracle 9i i am able to find one code which i pasted below. That works fine when i used harcoded value of comma separated strings in stored proc, but when passed it though input parameter of stored proc, it consider that string as single value and just loop through it once and insert the full string in column

CREATE OR REPLACE PROCEDURE SP_INSERTDOCUMENTDETAILS_BD
(
    BatchId  IN NUMBER,
    strDocumentIds IN varchar2
)
IS
  type table_varchar  is table of varchar2(32767);
  var_table_varchar  table_varchar;
begin
  var_table_varchar  := table_varchar(strDocumentIds);
  var_table_varchar  := table_varchar('004416979','004416987','004416988','004416989');

  for elem in 1 .. var_table_varchar.count loop
      Insert into documentdetails(DocumentID,BatchID,DocumentSRCGUID,Name,documentType,ExtractionStatus,InjectionStatus) 
      values(DocumentID_SEQ.NEXTVAL,BatchId,var_table_varchar(elem),'','',1,1);
  end loop;
end;
/
show errors;

Solution

  • Your table_varchar type does not magically parse a string containing comma-separated values into separate substrings. You still have to do that.

    Here's a nice little function which does the parsing for you. It uses the built-in system type DBMS_SQL.VARCHAR2A instead of your table type, but the result is similar:

    FUNCTION EXTRACT_TOKENS(p_string     IN VARCHAR2,
                            p_separators IN VARCHAR2)
      RETURN DBMS_SQL.VARCHAR2A
    IS
      arrTokens DBMS_SQL.VARCHAR2A;
    BEGIN
      WITH sel_string AS 
          (SELECT p_string AS fullstring FROM DUAL)
      SELECT SUBSTR(fullstring, beg + 1, end_p - beg - 1) AS token
        BULK COLLECT INTO arrTokens
        FROM (SELECT beg, LEAD(beg) OVER (ORDER BY beg) AS end_p, fullstring
                FROM (SELECT beg, fullstring
                        FROM (SELECT LEVEL beg, fullstring
                                FROM sel_string
                                CONNECT BY LEVEL <= LENGTH(fullstring))
                        WHERE INSTR(p_separators, SUBSTR(fullstring, beg, 1)) > 0
                      UNION ALL
                        SELECT 0, fullstring FROM sel_string
                      UNION ALL
                        SELECT LENGTH(fullstring) + 1, fullstring FROM sel_string))
        WHERE end_p IS NOT NULL AND
              end_p > beg + 1;
    
      RETURN arrTokens;
    END EXTRACT_TOKENS;
    

    You can use this by changing your procedure to:

    CREATE OR REPLACE PROCEDURE SP_INSERTDOCUMENTDETAILS_BD
    (
        BatchId  IN NUMBER,
        strDocumentIds IN varchar2
    )
    IS
      var_table_varchar  DBMS_SQL.VARCHAR2A ;
    begin
      var_table_varchar := EXTRACT_TOKENS(strDocumentIds, ',');
    
      for elem in 1 .. var_table_varchar.count loop
          Insert into documentdetails
            (DocumentID, BatchID, DocumentSRCGUID, Name, documentType, ExtractionStatus, InjectionStatus) 
          values
            (DocumentID_SEQ.NEXTVAL, BatchId, var_table_varchar(elem), ',' , 1, 1);
      end loop;
    end SP_INSERTDOCUMENTDETAILS_BD;
    

    Note that this still won't work because the field list on your INSERT statement has seven fields named while the VALUES clause only contains six values, but I'm sure you can fix that.