Grab Tablename From Stored SELECT Statement Using Oracle’s REGEXP Functions

I have an sqltext column in my database that contains select statements like

  • select firstname, lastname from employees

  • select firstname, lastname from managers
    where empid = 21

I need to extract the tablenames from these statements. Here is my cheeseball solution:

select
trim(REGEXP_REPLACE(replace(sqltext,chr(10),' '),
'(.*)( from )(.*)( where .*)' ||case when instr(replace(sqltext,chr(10), ' '), ' where ') = 0 then '?' end,
'-\3-',1,0,'i'))
from someTableThatContainsSqlText

Published in: on December 9, 2010 at 1:18 pm  Leave a Comment  
Tags: , ,

A List Function for Oracle

SQL Anywhere has a very convenient LIST function for combining rows of data into a single column.

Ex.

SELECT LIST( emp_id, ';' ORDER BY emp_lname ) AS "Sorted IDs"
FROM EMPLOYEE
GROUP BY dept_id

Sorted IDs
160;105;1250;247;266;249;445;…
1039;129;1142;195;667;1162;902;…
1336;879;586;390;757;148;1483;…
1751;591;1062;1191;992;888;318;…
1013;191;750;921;868;1658;703;…

Since I have to move between SQL Anywhere and Oracle quite often, I needed a way to duplicate, as much as possible, this function in Oracle.

Tom’s stringAgg routine is a great start. It is a good example of building a custom aggregate function in Oracle. However, it doesn’t lend itself to specifying the delimiter. Certainly you can use REPLACE, but if your strings contain commas, you’re out of luck.

Here is a solution, built on Tom’s StringAggType, that uses an object to pass in a delimiter. It’s a little clumsy to call, and doesn’t support DISTINCT, but it does work. Suggestions for improvement are welcome.

SQL> select deptid, list(listparm(lname, '|')) 
from emp 
group by deptid;

DEPTID       LIST(LISTPARM(LNAME,'|'))
----------   --------------------------------------------------------------------------------
10           Jones|Johnson|Hendricks
20           Sewell|Rogers|Yancy
30           Yost|Smith|Carter|Smith
40           Michaels

The Code:

drop type ListType
/

create or replace type ListParm as object
(
   theString varchar2(4000),
   is_Delimiter varchar2(100)
);
/

create or replace type ListType as object
(
   is_Delimiter varchar2(100),
   theString varchar2(4000),

   static function
        ODCIAggregateInitialize(sctx IN OUT ListType )
        return number,

   member function
        ODCIAggregateIterate(self IN OUT ListType ,
                             value IN ListParm )
        return number,

   member function
        ODCIAggregateTerminate(self IN ListType,
                               returnValue OUT  varchar2,
                               flags IN number)
        return number,

   member function
        ODCIAggregateMerge(self IN OUT ListType,
                           ctx2 IN ListType)
        return number
);
/

show errors

create or replace type body ListType
is

    static function ODCIAggregateInitialize(sctx IN OUT ListType)
    return number
    is
    begin
        sctx := ListType( ',', null );
        return ODCIConst.Success;
    end;

    member function ODCIAggregateIterate(self IN OUT ListType,
                                         value IN ListParm )
    return number
    is
    begin
        self.is_Delimiter := value.is_Delimiter;

        self.theString := self.theString || self.is_Delimiter || value.theString;
        return ODCIConst.Success;
    end;

    member function ODCIAggregateTerminate(self IN ListType,
                                           returnValue OUT varchar2,
                                           flags IN number)
    return number
    is
    begin
        returnValue := rtrim( ltrim( self.theString, self.is_Delimiter ), self.is_Delimiter );
        return ODCIConst.Success;
    end;

    member function ODCIAggregateMerge(self IN OUT ListType,
                                       ctx2 IN ListType)
    return number
    is
    begin
        self.theString := self.theString || self.is_Delimiter || ctx2.theString;
        return ODCIConst.Success;
    end;

end;
/

CREATE OR REPLACE FUNCTION List(input ListParm)
RETURN varchar2
PARALLEL_ENABLE AGGREGATE USING ListType;
/

Published in: on January 17, 2008 at 5:22 pm  Comments (11)