Как извлечь имена таблиц из файла тела пакета PL / SQL? - PullRequest
0 голосов
/ 06 апреля 2019

Мне нужно получить имена таблиц, запрашиваемые в файле пакета pl / sql.

Я знаю, что для этого в Notepad ++ есть опция regex, но я не знаю, какое регулярное выражение применять для получения имен таблиц (я понимаю, что это должно быть некоторое регулярное выражение, чтобы взять ключевое слово "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

Ответы [ 5 ]

2 голосов
/ 06 апреля 2019

Если вас интересуют только имена таблиц, которые напрямую связаны с 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';

DEMO

2 голосов
/ 06 апреля 2019

Насколько мне известно, никто не сделал это со 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 анализировала источник в поисках KEYWORDS и символов для управления механизмом состояний.Потребовалось несколько недель, чтобы уточнить и начать работать со всеми различными типами кодовой базы.

В конце концов, единственное, что он не мог сделать, - это динамические запросы, в которых имя таблицы было построено из значений переменных.Но обходной путь здесь заключался в том, чтобы захватить файлы tkprof и обработать их.

К сожалению, у меня больше нет исходного кода для этого.

Однако, если бы мне пришлось сделать это снова, яиспользует Lex / Yacc / Bison для синтаксического анализа SQL и построения системы на основе этих инструментов.

Быстрый поиск обнаружил следующее:

https://github.com/jgarzik/sqlfun

https://www.oreilly.com/library/view/flex-bison/9780596805418/ch04.html

Не малое начинание.

1 голос
/ 06 апреля 2019
  • Ctrl + H
  • Найти что: (?:\A(?:(?!FROM).)*|\G)FROM\s+(\w+(?:\s*,\s*\w+)*)(?:(?!FROM).)*
  • Заменить на: " # пробел и aдвойная кавычка
  • check Обтекание
  • check Регулярное выражение
  • CHECK . 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

Снимок экрана:

enter image description here

0 голосов
/ 09 апреля 2019

ранее упомянутых таблиц

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, если это необходимо если необходимо проверить непосредственно из файла, можно использовать сценарии UNIX (можно также использовать операции UTF_file), чтобы получать строку за строкой из файла и проводить сеанс sql для выполнения вышеуказанной проверки и отображения результатов

но, надеюсь, это даст наиболее точные результаты.

0 голосов
/ 06 апреля 2019

Вы можете использовать следующее регулярное выражение для поиска имен таблиц.

Регулярное выражение: FROM\s([^;]+)

Замена: \n%\1%\n

enter image description here

Затем следуйте этому ответу для замены других данных в файле.

...