-1

I know that there are REGEXP_ functions, but this ones return maximum 1 row when simply applied to a string var. I know that you can use it in a WHERE clause, but I need a way of dealing with large strings/text/clob vars not tables, so I would like to know if some function can return multiple substrings somehow (I am thinking at something like the explode() or - even better - preg_match() in PHP).

As APC suggested I am providing a sample string and examples of outcomes that I would like to get.. Like I said in the comments bellow, I wand to get the functions/procedures bodies (functions/procedures that are part of some packages) like this:

THE STRING:

  create or replace PACKAGE BODY export_db IS
  FUNCTION o_functie(ceva NUMBER) return boolean IS
  BEGIN
    RETURN null;
  END;
  FUNCTION o_functie(ceva NUMBER, altceva VARCHAR2) return boolean IS
  BEGIN
    RETURN null;
  END;
  PROCEDURE export_db_tabele IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT object_type,object_name FROM user_objects where object_type IN ( 'TABLE')) LOOP
        v_ddl := v_ddl || dbms_metadata.get_ddl(c.object_type, c.object_name)||';'||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('tabele', v_ddl);
  END;
  PROCEDURE export_db_restrictii IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT constraint_name FROM user_constraints) LOOP
        v_ddl := v_ddl || dbms_metadata.get_ddl('CONSTRAINT', c.constraint_name)||';'||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('restrictii', v_ddl);
  END;
  PROCEDURE export_db_secvente IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT sequence_name FROM user_sequences) LOOP
        v_ddl := v_ddl || dbms_metadata.get_ddl('SEQUENCE', c.sequence_name)||';'||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('secvente', v_ddl);
  END;
  PROCEDURE export_db_proceduri IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT OBJECT_NAME FROM user_objects up WHERE object_type = 'PROCEDURE') LOOP 
        v_ddl := v_ddl || dbms_metadata.get_ddl('PROCEDURE', c.OBJECT_NAME)||CHR(13)||CHR(10);   
      END LOOP;  
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('proceduri', v_ddl);
  END;
  PROCEDURE export_db_functii IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT OBJECT_NAME FROM user_objects uo WHERE object_type = 'FUNCTION' ) LOOP 
         v_ddl := v_ddl || dbms_metadata.get_ddl('FUNCTION', c.OBJECT_NAME)||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('functii', v_ddl);
  END;
  PROCEDURE export_db_pachete IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT OBJECT_NAME FROM user_objects uo WHERE object_type = 'PACKAGE' ) LOOP 
        v_ddl := v_ddl || dbms_metadata.get_ddl('PACKAGE', c.OBJECT_NAME)||CHR(13)||CHR(10);   
      END LOOP;   
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('pachete', v_ddl);
  END;
  PROCEDURE export_db_declansatoare IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT OBJECT_NAME FROM user_objects uo WHERE object_type = 'TRIGGER' ) LOOP 
        v_ddl := v_ddl || dbms_metadata.get_ddl('TRIGGER', c.OBJECT_NAME)||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('declansatoare', v_ddl);
  END;
END;

OUTCOMES would be:

ex:

  FUNCTION o_functie(ceva NUMBER, altceva VARCHAR2) return boolean IS
  BEGIN
    RETURN null;
  END;

and

PROCEDURE export_db_secvente IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT sequence_name FROM user_sequences) LOOP
        v_ddl := v_ddl || dbms_metadata.get_ddl('SEQUENCE', c.sequence_name)||';'||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('secvente', v_ddl);
  END;

IF you know any other method of geting those procedures/functions I am glad to give up parsing all this - from what I know - there is no select to do that... not even from user_source, user_procedures tables or other...

Michael
  • 4,786
  • 11
  • 45
  • 68
  • possible duplicate of [Does PL/SQL have an equivalent StringTokenizer to Java's?](http://stackoverflow.com/questions/1520733/does-pl-sql-have-an-equivalent-stringtokenizer-to-javas) – APC Nov 11 '11 at 21:25
  • I'm not a PHP guru, but PREG_MATCH() and EXPLODE() seem to produce diiferent outcomes. So it would be really useful if you could give us a sample string and your desired outome. – APC Nov 11 '11 at 21:27
  • @APC The string would be a package body, since in Oracle I couldn't find a way of getting functions/procedures bodies inside of the first ones like you can get for the ones in the main schema (witch are not in packages). Therefor I need to parse the string... – Michael Nov 11 '11 at 21:44
  • Maybe I'm being dense but I really don't understand what any of that means. Is it really tto hard for you to provide an example? – APC Nov 11 '11 at 21:52

1 Answers1

2

Something like this maybe:

CREATE OR REPLACE FUNCTION explode(longline varchar)
  RETURN sys.dbms_debug_vc2coll PIPELINED
IS  
  pos PLS_INTEGER;
  lastpos PLS_INTEGER;
  element varchar(2000);
BEGIN
   lastpos := 1;
   pos := instr(longline, ',');

   while pos > 0 loop
      element := substr(longline, lastpos, pos - lastpos);
      lastpos := pos + 1;
      pos := instr(longline, ',', lastpos);
      pipe row(element);
   end loop;

   if lastpos <= length(longline) then
      pipe row (substr(longline, lastpos));
   end if;

   RETURN;
END;  
/

This can be used like this:

SQL> select * from table(explode('1,2,3'));

COLUMN_VALUE
---------------------------------------------
1
2
3
SQL>

If you are not on 11.x you need to define the return type yourself:

create type char_table as table of varchar(4000);

and change the function declaration to:

CREATE OR REPLACE FUNCTION explode(longline varchar)
  RETURN char_table pipelined
.....
  • Thank's a lot! Although I would need thomething more adjustable so I can get substrings based on variable delimiters... I will see if I can make this work for me! Thank's again! – Michael Nov 11 '11 at 21:40
  • Just pass the delimiter as a parameter to the function. –  Nov 11 '11 at 21:58
  • Yes, I added a new parameter to the function (delimiter), and because there was no delimiter that matched exactly the substrings I needed, I had to use REGEXP_ functions to insert a custom delimiter inside of the string to explode. To be more specific (if this could help someone), in a package body you have more procedures/functions that start with a "PROC.." or "FUNC.." and ends with ";". But while inside of a particular procedures might be a lot of other ";" you can not explode by ";". So I used REGEXP_REPLACE to create a new dedicated delimiter between any ";" and "PROCEDURE" or "FUNCTION". – Michael Nov 15 '11 at 12:24