Daddy said:
...could you give me a short explanation of how that works?
People say that I don't do anything "short". <grin>
But I'll try to be brief, yet clear, in my explanation of how matrix works. Let's analyse each procedural statement in the function. Here is a restatement of the code, followed by statement-by-statement explanations:
Code:
CREATE OR REPLACE FUNCTION matrix (query_in in VARCHAR2) RETURN VARCHAR2 IS
incoming varchar2(4000);
hold_result varchar2(4000);
c sys_refcursor;
Begin
open c for query_in;
loop
fetch c into incoming;
exit when c%notfound;
hold_result := hold_result||','||incoming;
end loop;
return ltrim(hold_result,',');
END;
1)
open c for query_in; -- Populate a cursor named "c" with the results of a query. The query to use to populate the cursor is the query we pass into the function using the argument "query_in". (Remember, we re-execute this function for each row that results from the GROUP BY statement in the calling (outer) query. So, each row in the outer query calls this "matrix" function. The query we pass to the "matrix" function gets
recoded for each calling row. Using your data, there are two grouped rows (since we GROUP BY dt,key). The first row calls "matrix", passing this query into the function:
Code:
select channel from feed
where dt = '5/1/2007'
and key = '5059447697749064422-720588443029085730'
If you were to execute the above first query by hand, the results would be:
So, those two "rows" of data would reside in the cursor, "c".
2)
loop...end loop; -- Execute the intervening commands until something gets you out of the loop.
3)
fetch c into incoming; -- copy the first "row" of data from "c" ("Feeds") into the 4000-byte-maximum memory variable, "incoming".
4)
exit when c%notfound; -- Check the current value of the automatically created, boolean (TRUE/FALSE/NULL) cursor variable, "notfound". If the "fetch" command successfully retrieved a row of data from the cursor "c", then the value of "c%notfound" is
false; eventually (when we loop enough times to have read all of the row data in "c"), Oracle will "not find" data, so the value of "c%notfound" becomes TRUE. When "c%notfound" becomes TRUE, then execution passes to the command following the "END LOOP" statement.
5)
hold_result := hold_result||','||incoming; -- "hold_result" starts out NULL (since we did not initialise "hold_result" to any value). The first time through, the above command stores:
...in "hold_result".
6) (reaches the "END LOOP" and goes back to the top of the LOOP, and executes at Step 3. At Step 5, the contents of "hold_result" become:
The next time through the LOOP, Oracle finds no data and exits the LOOP to...
7)
return ltrim(hold_result,','); -- Oracle "left trims" any commas from the beginning of "hold_result", yielding "
Feeds,Search". This value RETURNs to the calling program.
Let me know if questions remain.
![[santa] [santa] [santa]](/data/assets/smilies/santa.gif)
Mufasa
(aka Dave of Sandy, Utah, USA)
[I provide low-cost, remote Database Administration services:
www.dasages.com]