I developed this code in 1999 when I used to code pl/sql for a living.
We used to have an order-entry system where the customer used to order multiple items and each item along with quantity used to sit as a row in the order detail table.
Our team wanted to avoid making multiple calls to the database for each order item.Therefore we told the UI folks to send us the customer "ordered" items as a single string list separated by a de-limiter and inside the procedure we would split the individual order items into a pl/sql table and then insert it into the order detail table.
I believe oracle has an in-built package to achieve the same in dbms_utility but I believe the below code is more robust in the sense that this could handle NULL values too.
For example if somebody passed the following string (with * delimiter)
abc*xyz**mno
My procedure would break this up into
1.abc
2.xyz
3.NULL
4.mno
Likewise something like *abc**cvs* would be broken up as
1.NULL
2.abc
3.NULL
4.cvs
5.NULL
Here is the code to achieve the same.....
CREATE OR REPLACE PACKAGE pk_genutilitypkg
AS
/*
Generic String Parser: provide a delimiter and it returns an
index-by table of the individual elements of the string that are
separated by the specified delimiter.
Author: "GAUTHAM CHANDRASEKARAN" <gautha@hotmail.com>
*/
TYPE t_string IS TABLE OF VARCHAR2(2000)
INDEX BY BINARY_INTEGER;
m_ctr NUMBER(5);
m_pos NUMBER(5);
PROCEDURE sp_parsestring (
p_string IN VARCHAR2,
delimiter IN VARCHAR2,
p_t_string OUT t_string);
END pk_genutilitypkg;
/
CREATE OR REPLACE PACKAGE BODY pk_genutilitypkg
AS
PROCEDURE sp_parsestring (
p_string IN VARCHAR2,
delimiter IN VARCHAR2,
p_t_string OUT t_string)
IS
m_string VARCHAR2(4000);
BEGIN
/* Raise a Error if the length of the delimiter is not 1 */
IF LENGTH (delimiter) != 1
THEN
raise_application_error (-20001,
'Delimiter should be of only one character');
RETURN;
END IF;
m_string := p_string;
m_ctr := 1;
LOOP
m_pos := INSTR (m_string, delimiter);
IF m_pos > 1
THEN
p_t_string (m_ctr) := SUBSTR (m_string, 1, m_pos - 1);
IF (m_pos < LENGTH (m_string))
THEN
m_string := SUBSTR (
m_string,
m_pos + 1,
LENGTH (m_string) - m_pos
);
ELSIF m_pos = LENGTH (m_string)
THEN
m_ctr := m_ctr + 1;
p_t_string (m_ctr) := NULL;
EXIT;
END IF;
ELSIF m_pos = 1
THEN
p_t_string (m_ctr) := NULL;
IF m_pos < LENGTH (m_string)
THEN
m_string := SUBSTR (
m_string,
m_pos + 1,
LENGTH (m_string) - m_pos
);
ELSIF m_pos = LENGTH (m_string)
THEN
m_ctr := m_ctr + 1;
p_t_string (m_ctr) := NULL;
EXIT;
END IF;
ELSIF m_pos = 0
THEN
p_t_string (m_ctr) := m_string;
EXIT;
END IF;
m_ctr := m_ctr + 1;
END LOOP;
END;
END pk_genutilitypkg;
/
declare
x pk_genutilitypkg.t_string;
str1 varchar2(200):='121,234,345,657,890';
begin
pk_genutilitypkg.sp_parsestring(str1,',',x);
for i in 1..x.count
loop
dbms_output.put_line(x(i));
end loop;
end;
/
SQL> declare
2 x pk_genutilitypkg.t_string;
3 str1 varchar2(200):='121,234,345,657,890';
4 begin
5 pk_genutilitypkg.sp_parsestring(str1,',',x);
6
7 for i in 1..x.count
8 loop
9 dbms_output.put_line(x(i));
10
11 end loop;
12 end;
13 /
PL/SQL procedure successfully completed.
SQL> set serverout on
SQL> /
121
234
345
657
890
PL/SQL procedure successfully completed.
No comments:
Post a Comment