| Extracting SQL statements from PL/SQL [2008.02.21] Bookmark (1.0.0.0) Maybe this is just a solution for a problem, but it looked like a neat challenge. Since I'm also a bit lazy I decided for a quick solution including regular expressions and DBMS_OUTPUT for displaying the result. Yet I've included a check for comments, so SQL-Statements inside a line "--" or line spanning "/* */" comment should be ignored.
Here's the package I wrote, I called it util_xref (for cross reference):
CREATE OR REPLACE PACKAGE util_xref
IS
PROCEDURE find_sql(
p_name IN user_source.name%TYPE
, p_type IN user_source.type%TYPE
)
;
END util_xref;
/
SHOW ERROR
CREATE OR REPLACE PACKAGE BODY util_xref
IS
PROCEDURE find_sql(
p_name IN user_source.name%TYPE
, p_type IN user_source.type%TYPE
)
IS
CURSOR cur_source(
p_name IN user_source.name%TYPE
, p_type IN user_source.type%TYPE
)
IS
/* SELECT on user_source
*/
SELECT line -- Line number
, text -- Line (source code)
FROM user_source
WHERE name = UPPER(p_name)
AND type = UPPER(p_type)
ORDER BY line
;
v_text user_source.text%TYPE;
v_count NUMBER;
v_source CLOB;
v_search CLOB;
v_sql CLOB;
BEGIN
FOR rec_source IN cur_source(p_name, p_type)
LOOP
-- ignore line comments
v_text := REGEXP_REPLACE(rec_source.text, '--.*');
v_source := v_source || v_text;
END LOOP;
-- replace line spanning comments
v_search := REGEXP_REPLACE(v_source, '/*[^*]**/');
-- Print SQL Statements
v_count := 1;
LOOP
v_sql := REGEXP_SUBSTR(v_search, ' *(select|insert|update|delete|merge|with)[^;]*from[^;]*;', 1, v_count, 'i');
EXIT WHEN NVL(LENGTH(v_sql), 0) = 0;
v_count := v_count + 1;
DBMS_OUTPUT.put_line(v_sql);
END LOOP;
END find_sql;
END util_xref;
/
SHOW ERROR
And I tested it of course against itself:
SET LINESIZE 255
SET SERVEROUTPUT ON
BEGIN
util_xref.find_sql('util_xref', 'package body');
END;
/
Looks ok to me, however the first line got moved to the left, which is related to DBMS_OUTPUT which doesn't like leading spaces. |