#sql #oracle #plsql
#sql #Oracle #plsql
Вопрос:
Мне нужно получить имя пакета и первые строки комментариев из файла пакета PL / SQL (спецификация и / или тело) или из пакета, скомпилированного в BD.
Я знаю, что существует скрипт для получения имени пакета, но для этого нужно было получить описание из пакета.
Например, если мне нужно получить имена пакетов, я могу выполнить этот select:
select * from all_objects where object_name like 'pack%';
Но если мне нужно получить в результате запроса плюс имя пакета, первые строки из package. Если пакет начинается с:
CREATE OR REPLACE PACKAGE BODY pack_test AS
/* **************************************************** */
* Description: maintenance package from suppliers table *
* Author: reymagnus *
* Creation date: 09/04/2019 *
* (another comments) *
* **************************************************** */
Я ожидаю получить это:
Object_Type Object_Name Description
=========== =========== ===========
PACKAGE pack_test maintenance package from suppliers table
Или
Object_Type Object_Name Description_line
=========== =========== ================
PACKAGE pack_test CREATE OR REPLACE PACKAGE BODY pack_test AS
PACKAGE pack_test /* **************************************************** */
PACKAGE pack_test * Description: maintenance package from suppliers table *
Возможно, мне нужно объединить таблицы all_objects и all_source и получить только <= 3 строки.
Комментарии:
1. Может быть, вы делаете (выглядит как хорошая идея). Вы пробовали это?
2. Что касается автора и даты, я думаю, что подобные вещи не должны быть в заголовке пакета. В конце концов, через некоторое время будут внесены изменения, и у вас будет несколько авторов и несколько дат. Вместо этого сохраните ваши изменения в системе управления версиями, чтобы у вас был автор дата сообщение о фиксации / описание изменения для каждого изменения, которое вы вносите в исходный код.
Ответ №1:
Я бы получил имя пакета из all_objects
, потому что оно там в любом случае.
Синтаксический анализ комментария должен быть выполнимым. Просто найдите строку, начинающуюся с * Description:
, и возьмите остальную часть этой строки.
REGEXP_SUBSTR
может быть хорошей функцией для анализа этого или некоторых базовых строковых функций, таких как:
select
o.OWNER,
o.OBJECT_NAME,
( select
MIN(TRIM(SUBSTR(s.TEXT, INSTR(s.TEXT, 'Description:') 12)))
from
ALL_SOURCE s
where
s.NAME = o.OBJECT_NAME
and s.OWNER = o.OWNER
and s.LINE <= 5
and s.TEXT like '% Description:%') as DESCRIPTION
from
ALL_OBJECTS o
where
o.OBJECT_TYPE = 'PACKAGE';
Следует отметить, что эта проверка немного грубовата. Теоретически текст Description:
также может быть частью некоторого кода или запроса, поэтому теоретически вы можете получить ложноположительный результат и получить странное описание.
Кроме того, эта проверка довольно строгая. Если вы ввели description
(нижний регистр), или description :
(пробел перед двоеточием) или *Description:
(между звездочкой и словом нет пробела), совпадения не будет.
Кроме того, я использовал MIN
для получения любого описания на случай, если их несколько. Лично я думаю, что это нормально для обнаружения подобных крайних случаев. Вы также могли бы использовать LIST_AGG
для возврата их всех, что имеет приятное преимущество, заключающееся в разрешении многострочных описаний … 🙂
Ответ №2:
В качестве альтернативы вы можете создать таблицу ведения журнала
create table t_log( obj_name varchar2(35), obj_type varchar2(35), obj_rows varchar2(4000) );
и заполнить с помощью user_source
словарного представления и ограничить тремя строками
declare
v_plsql_unit varchar2(35):= 'my_package';
begin
for c in ( select * from user_source s where s.name = upper(v_plsql_unit) order by s.line )
loop
begin
insert into t_log values( c.name, c.type, c.text );
exit when c.line = 3;
end;
commit;
end loop;
end;
Ответ №3:
описания спецификации пакета и тела пакета в основном следуют за символами ‘/ *’ или ‘—‘, и не существует критериев, по которым ключевое слово description должно присутствовать там, если только это не бизнес-критерии. если это критерий, то можно использовать ключевое слово, иначе можно сослаться на приведенный ниже запрос и изменить его в соответствии с потребностями.
-- package to query: sample_pkg
select o.owner,
o.object_name,
(select listagg(a.text ) WITHIN GROUP (ORDER BY a.line asc)
from all_source a
where a.name =o.object_name
and a.line between (select b.line from all_source b where b.name=a.name and b.text like '%'||chr(47)||'*%')
and (select c.line from all_source c where c.name =a.name and c.text like '%*'||chr(47)||'%')
) description
from all_objects o
where o.object_type like 'PACK%'
and o.object_name like 'SAMP%';
-- output
OWNER OBJECT_NAME DESCRIPTION
SQL_user SAMPLE_PKG /*
sample spec description
*/