Monday, November 27, 2006

PL/SQL: Joinrows - Convert multiple [returned cursor] rows into one row

This routine converts multiple rows into a single row. The trick is to pass the data via a SYS_REFCURSOR (see the CURSOR call in the example). Example Usage :

select joinrows(cursor(select contract_id from contract where rownum < 10 )) from dual;
CREATE OR REPLACE FUNCTION joinrows(
 sysref_cursor_in      sys_refcursor,
 s_delimiter_in        VARCHAR2 := ',' )
RETURN VARCHAR2
IS
   s_value            VARCHAR2(32767) := Null;
   s_result           VARCHAR2(32767) := Null;
   s_delimiter        VARCHAR2(100) := NVL(s_delimiter_in,',');
BEGIN

   LOOP
      FETCH sysref_cursor_in
         INTO s_value;

      EXIT WHEN sysref_cursor_in%NOTFOUND;

      IF (s_result IS NOT NULL) THEN
       s_result := s_result||s_delimiter;
      END IF;

      s_result := s_result||s_value;

   END LOOP;

   RETURN s_result;

END joinrows;

Results:

0,2,3,9,37,404,818,991,1178

6 comments:

Anonymous said...

Be warned -- I've tried to use this function with terrible results. Sorry, I tried it as-is, and also adding a CLOSE cursor statement before returning. Both were equally horribly slow.

Jason said...

Yeah, I can't say that it's fast. I needed it for a specific situation. It works, but you're right, it's not optimized for speed.

Anonymous said...

I'm new to pl/sql, your function seems like a solution I need for my situation.

I use your function joinrows in the package, and i'm trying to run the cursor as below, but it's not working for me by giving me the error message "FROM keyword not found when expected". Please help. Thanks.

CURSOR c1(tid integer) IS
select joinrows(cursor(select distinct report_id
from reports
where tag_id = tid));

Jason said...

Oops,typo in example. Fixed.

Anonymous said...

Thanks! It gives me correct output when I ran the SQL alone, however, when I ran as the cursor in the package and fetch to a variable, it gives me nothing. Any ideas? Thanks.

Jason said...

Sorry, I just don't have enough information to answer your question. I can tell that it works from within packages.