[英]How extract table names from PL/SQL package body file?
我需要在pl / sql软件包文件中查询表名称。
我知道regex在Notepad ++中为此提供了一个选项,但是我不知道要申请哪种正则表达式来获取表名(我知道必须是一些正则表达式才能使用关键字“ FROM”并在空格后获取下一个字符串, 我认同)。
对于下一个示例代码:
CREATE OR REPLACE PACKAGE BODY pac_example AS
FUNCTION f1 RETURN NUMBER IS
BEGIN
SELECT * FROM table1;
RETURN 1;
END f1;
FUNCTION f2 RETURN NUMBER IS
BEGIN
SELECT * FROM table2;
RETURN 1;
END f2;
END pac_example;
我希望全部替换并仅使用表名获取文件 :
table1
table2
如果您只对直接从PACKAGE BODY
引用的表名感兴趣,则一种简单而直接的方法是查询all_dependencies
或user_dependencies
。
SELECT owner,
referenced_name as table_name
FROM all_dependencies
WHERE type IN (
'PACKAGE BODY'
) AND name IN (
'PAC_EXAMPLE'
) AND referenced_type = 'TABLE';
据我所知,没有人能做到100%准确。 您获得的最接近的是ALL / DBA_DEPENDENIES,但是不会告诉您是否在SELECT,INSERT,UPDATE或DELETE中访问了表。
但是它将解析同义词。
这样做的缺点是它将不包括动态SQL中引用的表。
如果您的数据库对表使用特定的命名约定(例如Tnnn_XXXXX),则可以执行以下操作:
SELECT DISTINCT c.text, c.name, c.type, t.table_name
FROM user_source c, user_tables t
WHERE UPPER(t.text) like '%' || t.name_name || '%' -- Maybe REGEXP_LIKE better
ORDER BY 2, 1, 4;
几十年前,我从事一个项目,他们想要一个CRUD程序矩阵(PLSQL,SQL,Oracle Forms / Reports,Pro C,Pro COBOL)以及每个表访问什么。
当时唯一可用的解决方案是我编写一个解析器(用C语言编写),该解析器对代码库进行解析以查找SQL并对其进行处理。 我什至报告了列和表格。 C程序分析了源代码,寻找关键字和字符来控制状态引擎。 优化和使用所有不同的代码库类型花了两个星期的时间。
最后,它唯一不能做的就是动态查询,其中表名是根据变量值构建的。 但是,此处的解决方法是捕获tkprof文件并对其进行处理。
可悲的是,我没有这个的源代码了。
但是,如果我要再做一次,我将使用Lex / Yacc / Bison解析SQL并围绕这些工具构建系统。
快速搜索发现:
https://github.com/jgarzik/sqlfun
https://www.oreilly.com/library/view/flex-bison/9780596805418/ch04.html
一项不小的任务。
(?:\\A(?:(?!FROM).)*|\\G)FROM\\s+(\\w+(?:\\s*,\\s*\\w+)*)(?:(?!FROM).)*
"
#a空格和双引号 . matches newline
. matches newline
说明:
(?: # start non capture group
\A # beginning of file
(?:(?!FROM).)* # Tempered greedy token, make sure we haven't FROM before
| # OR
\G # restart from last match position
) # end group
FROM\s+ # literally FROM followed by 1 or more spaces
( # start group 1
\w+ # 1 or more word characters (table name)
(?:\s*,\s*\w+)* # non capture group spaces comma spaces and 1 or more word characters, optional more tables
) # end group
(?:(?!FROM).)* # Tempered greedy token, make sure we haven't FROM
替代:
$1 # content of group 1, table name
屏幕截图:
前面提到的表
all_dependencies or user_dependencies
可以列出前面提到的依赖项,但不会涵盖动态查询。 如果在记事本中使用“ from”之类的关键字进行搜索,则仅覆盖“ From”语句之后的语句所引用的表。
可以考虑使用以下代码段进行全面分析:-逐行,逐词并分析表格(请参阅您提到的示例)
declare
l_line varchar2(2000);
ln_start_string number;
ln_last_string number;
ln_string_length number;
l_word varchar2(4000);
l_table_flag varchar(2):='N';
cursor l_pkg_body_cur
is
select TEXT from all_source where upper(name) like upper('pac_example') and type = 'PACKAGE BODY';
-- to get the source compiled in package boby, mentioned the package to be searched here
begin
for rec in l_pkg_body_cur
loop
-- line by line processing
select TRIM(rec.text) into l_line from dual;
ln_string_length := length(l_line);
loop
-- word by word processing
l_table_flag :='N';
select instr(l_line,' ') into ln_last_string from dual;
select substr(l_line,0,ln_last_string) into l_word from dual;
begin
select 'Y' into l_table_flag from all_tables where upper(table_name) like upper(trim(l_word)) and rownum=1; -- to validate it is table or not
exception
when others then
l_table_flag := 'N';
end;
IF l_table_flag = 'Y'
then
dbms_output.put_line(trim(l_word) ); -- table name
end if;
select length (l_word) into ln_start_string from dual;
select trim(substr(replace(l_line,';',null),ln_start_string)) into l_line from dual;
exit when l_line is NULL;
end loop;
end loop;
end;
--output:
Statement processed.
table1
table2
以类似的方式可以根据需要更改此查询,以查找所需的视图或同义词,方法是更改基表-all_views,all_synonyms。
这就像最简单的方法一样-可能需要更多的处理时间取决于包的大小,如果需要,可以直接使用UNIX脚本(也可以使用UTF_file操作)来使用UNIX脚本(如果需要直接从文件中进行检查)来完成相同的操作。从文件逐行进行并具有sql会话以执行上述验证并显示结果
希望这样可以提供最准确的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.