Порядок сборки Oracle и МН зависимости от пакета / зависимости от пакета SQL

Я пытаюсь создать список МН зависимостей от пакета / зависимостей от пакета SQL так, чтобы я мог помочь настроить автоматизированный сценарий сборки для своих пакетов для работы тестового сервера. Существует ли способ запуститься с единственного пакета ("корневой" пакет, определенный по имени, идеально) и затем найти все зависимости и порядок, в котором они должны быть скомпилированы? Зависимости уже полностью разрешены в моей персональной схеме (так, по крайней мере, я должен где-нибудь запустить - но куда я иду затем?).

(Oracle 10.2)

Править:

Инструмент сборки, который используется, будет использовать порядок сборки и получит те файлы в порядке от управления исходным кодом и затем передаст их Oracle для компиляции (сам фактический инструмент сборки записан в Python или Java или обоих - у меня нет доступа к источнику). В основном инструменту сборки нужен, как введено список файлов для компиляции в порядке, они должны быть скомпилированы в, и доступ к тем файлам в управлении исходным кодом. Если это будет иметь это, то все будет работать вполне приятно.

Править:

Спасибо за аккуратные сценарии. К сожалению, процесс сборки главным образом вне моих рук. Процесс базируется вокруг инструмента сборки, который был создан поставщиком продукта, с которым мы интегрируемся, который является, почему единственные исходные данные, которые я могу дать процессу сборки, являются списком файлов в порядке, они должны быть встроены. Если существует ошибка компилятора, сбои инструмента сборки, мы должны вручную отправить запрос для новой сборки. Таким образом, список файлов в порядке, они должны быть скомпилированы, важен.

Править:

Найденный этим: http://www.oracle.com/technology/oramag/code/tips2004/091304.html Дает мне зависимости любого объекта. Теперь я просто должен разобраться в упорядочивании... Если я получу что-то работа, то я отправлю ее здесь.

Править: (с кодом!)

Я знаю, что в целом, этот вид вещи не необходим для Oracle, но ни для кого, кто все еще заинтересовал...

Я починил немного сценария, который, кажется, может добраться, сборка заказывают таким образом, что все пакеты будут созданы в правильном порядке без связанных с зависимостью ошибок (относительно pacakges) в первый раз вокруг:

declare

    type t_dep_list is table of varchar2(40) index by binary_integer;
    dep_list t_dep_list;
    i number := 1;
    cursor c_getObjDepsByNameAndType is
    --based on a query found here: http://www.oracle.com/technology/oramag/code/tips2004/091304.html
        select lvl, u.object_id, u.object_type, LPAD(' ', lvl) || object_name obj
        FROM (SELECT level lvl, object_id
               FROM SYS.public_dependency s
               START WITH s.object_id = (select object_id
                                         from user_objects
                                         where object_name = UPPER(:OBJECT_NAME)
                                               and object_type = UPPER(:OBJECT_TYPE))
               CONNECT BY s.object_id = PRIOR referenced_object_id
               GROUP BY level, object_id) tree, user_objects u
        WHERE tree.object_id = u.object_id
              and u.object_type like 'PACKAGE%' --only look at packages, not interested in other types of objects
        ORDER BY lvl desc;

    function fn_checkInList(in_name in varchar2) return boolean is
    begin
        for j in 1 .. dep_list.count loop
            if dep_list(j) = in_name then
                return true;
            end if;
        end loop;
        return false;
    end;



    procedure sp_getDeps(in_objID in user_objects.object_id%type, in_name in varchar2) is
        cursor c_getObjDepsByID(in_objID in user_objects.object_id%type) is
        --based on a query found here: http://www.oracle.com/technology/oramag/code/tips2004/091304.html
            select lvl, u.object_id, u.object_type, LPAD(' ', lvl) || object_name obj
            FROM (SELECT level lvl, object_id
                   FROM SYS.public_dependency s
                   START WITH s.object_id = (select uo.object_id
                                             from user_objects uo
                                             where uo.object_name =
                                                   (select object_name from user_objects uo where uo.object_id = in_objID)
                                                   and uo.object_type = 'PACKAGE BODY')
                   CONNECT BY s.object_id = PRIOR referenced_object_id
                   GROUP BY level, object_id) tree, user_objects u
            WHERE tree.object_id = u.object_id
                  and u.object_id <> in_objID --exclude self (requested Object ID) from list.
            ORDER BY lvl desc;
    begin
        --loop through the dependencies
        for r in c_getObjDepsByID(in_objID) loop
            if fn_checkInList(trim(r.obj)) = false and (r.object_type = 'PACKAGE' or r.object_type = 'PACKAGE BODY') and
               trim(r.obj) <> trim(in_name) then
                dbms_output.put_line('checking deps of: ' || r.obj || ' ' || r.object_id || ' level: ' || r.lvl);
                --now for each dependency, check the sub-dependency
                sp_getDeps(r.object_id, trim(r.obj));
                --add the object to the dependency list.
                dep_list(i) := trim(r.obj);
                i := i + 1;
            end if;
        end loop;
    exception
        when NO_DATA_FOUND then
            dbms_output.put_line('no more data for: ' || in_objID);
    end;

begin

    for r in c_getObjDepsByNameAndType loop
        dbms_output.put_line('top-level checking deps of: ' || r.obj || ' ' || r.object_id || ' level: ' || r.lvl);
        sp_getDeps(r.object_id, trim(r.obj));
    end loop;

    dbms_output.put_line('dep count: ' || dep_list.count);
    for j in 1 .. dep_list.count loop
        dbms_output.put_line('obj: ' || j || ' ' || dep_list(j));
    end loop;
end;

Я знаю, что это не самый симпатичный код (globals повсеместно, и т.д.... тьфу), и я, вероятно, повторно отправлю его, если я могу заставить шанс этим днем очищать его, но прямо сейчас, это производит порядок сборки, который, кажется, работает в первый раз без проблем.

:OBJECT_NAME должен быть корневой объект, из которого Вы хотите проследить все зависимости и порядок сборки. Для меня это - основной пакет с отдельным методом, который является точкой входа к остальной части системы.

:OBJECT_TYPE Я главным образом ограничил PACKAGE BODY, но это не должно быть слишком много работы для включения других типов, таких как триггеры.

Одна последняя вещь, объект, указанный :OBJECT_NAME не появится в выводе, но это должен быть последний объект, таким образом, необходимо будет добавить, что к сборке перечисляют вручную.

ОБНОВЛЕНИЕ: Я просто обнаружил user_dependencies и all_dependencies, этот код мог, вероятно, быть сделан намного более простым теперь.

7
задан FrustratedWithFormsDesigner 4 February 2010 в 14:59
поделиться

6 ответов

реальное решение: Похоже, скрипт, приведённый выше, даёт правильный порядок сборки. Возможно, его можно переписать "лучше", но я оставлю это как упражнение для читателя. ;)

После некоторого обсуждения инструмент сборки выполнит n (4, на самом деле) сборки подряд перед тем, как сообщить об ошибках. Это также поможет разрешить ошибки компиляции зависимостей, если порядок сборки неправильный, но я бы предпочел, чтобы порядок сборки был правильным с первого раза.

-1
ответ дан 7 December 2019 в 01:20
поделиться

Посмотрите на следующий скрипт из http://www.orcle-base.com/articles/misc/recompilinginvalidschemabjects.php

SET SERVEROUTPUT ON SIZE 1000000
BEGIN
  FOR cur_rec IN (SELECT owner,
                         object_name,
                         object_type,
                         DECODE(object_type, 'PACKAGE', 1,
                                             'PACKAGE BODY', 2, 2) AS recompile_order
                  FROM   dba_objects
                  WHERE  object_type IN ('PACKAGE', 'PACKAGE BODY')
                  AND    status != 'VALID'
                  ORDER BY 4)
  LOOP
    BEGIN
      IF cur_rec.object_type = 'PACKAGE' THEN
        EXECUTE IMMEDIATE 'ALTER ' || cur_rec.object_type || 
            ' "' || cur_rec.owner || '"."' || cur_rec.object_name || '" COMPILE';
      ElSE
        EXECUTE IMMEDIATE 'ALTER PACKAGE "' || cur_rec.owner || 
            '"."' || cur_rec.object_name || '" COMPILE BODY';
      END IF;
    EXCEPTION
      WHEN OTHERS THEN
        DBMS_OUTPUT.put_line(cur_rec.object_type || ' : ' || cur_rec.owner || 
                             ' : ' || cur_rec.object_name);
    END;
  END LOOP;
END;
/
2
ответ дан 7 December 2019 в 01:20
поделиться

Вам не нужен порядок сборки - просто постройте пакеты с помощью «Создать или заменить ...» на файловой основе, а затем составьте их в двухуровневом вложенном цикле - каждый проход во внутреннем Цикл компилирует все, что все еще неверно, и внешний цикл используется для проверки количества оставшихся неверных объектов и установить какой-то порог для максимальных исполнений внутреннего цикла. На практике я никогда не видел, что количество проходов необходимо превышать трех.

Если у вас есть несколько схем, участвующих в зависимостях, посмотрите на скрипт Oracles utlrp.sql, который работает через схемы и устанавливает некоторую инфраструктуру для управления процессом - однако требуется привилегированная учетная запись.

Кроме того, если вы продлите свой исходный элемент управления, чтобы включить представления, убедитесь, что сценарии используют «Создать или заменить принудительный вид ...» для создания представлений, которые имеют неудовлетворенные зависимости во время их создания.

Пример скрипта, который я использую:

set serveroutput on
declare
 cursor invalidObjCur is 
  select object_name, object_type
    from user_objects
    where status <> 'VALID'
    ;
 compileStmt varchar2(4000); 
 passCount pls_integer := 0;
 maxPasses pls_integer := 5;
 lastInvalidCount pls_integer := 32000; 
 objectCount pls_integer;
 continue boolean := TRUE;

begin
 dbms_output.enable(1000000);
 while (continue) loop
   passCount := passCount + 1;
   dbms_output.put_line('Pass '||passCount);
   objectCount := 0;
   for curRow in InvalidObjCur loop
    if curRow.object_type = 'PACKAGE BODY' then
        compileStmt := 'alter PACKAGE '||curRow.object_name||' compile body';
    else
        compileStmt := 'alter '||curRow.object_type||' '||
        chr(34)||curRow.object_name||chr(34)||' compile';
    end if;
    begin
      execute immediate compileStmt;
    exception when others then
      null;
    end;
   objectCount := objectCount + 1;
   end loop;
   dbms_output.put_line('Recompilations attempted: '||objectCount);
   continue := (passCount < maxPasses) and (objectCount < lastInvalidCount);
   lastInvalidCount := objectCount;
 end loop;
dbms_output.put_line('***** Remaining Invalid ********');
for curRow in InvalidObjCur loop
 dbms_output.put_line(curRow.object_type||' '||curRow.object_name);
end loop; 
dbms_output.put_line('********************************');
end;    
/
0
ответ дан 7 December 2019 в 01:20
поделиться

Добавьте следующую команду в начало вашего скрипта:

SET VERIFY OFF

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

Вы можете позже запросить DBA_ERRORS, чтобы получить все ошибки и предупреждения в ваших пакетах, представлениях и типах.

0
ответ дан 7 December 2019 в 01:20
поделиться

Если вы действительно имеете дело только с пакетами PL / SQL, вам не нужно попотеть над порядком сборки. Просто сначала соберите все спецификации пакета. Затем вы можете развернуть все тела пакета, и они будут скомпилированы, потому что их зависимости являются спецификациями пакета.

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

править

Похоже, они будут делать инкрементные и "чистые" сборки, поэтому порядок сборки будет иметь наибольшее значение , когда они будут очищать среду и перестройте ее.

Это ничего не меняет.

Вот расширенный пример. У меня есть схема с тремя пакетами ....

SQL> select object_name, object_type, status
  2  from user_objects
  3  order by 1, 2
  4  /

OBJECT_NAME     OBJECT_TYPE     STATUS
--------------- --------------- -------
PKG1            PACKAGE         VALID
PKG1            PACKAGE BODY    VALID
PKG2            PACKAGE         VALID
PKG2            PACKAGE BODY    VALID
PKG3            PACKAGE         VALID
PKG3            PACKAGE BODY    VALID

6 rows selected.

SQL>

Интересно то, что процедура в PKG1 вызывает процедуру из PKG2, процедура в PKG2 вызывает процедуру из PKG3, а процедура в PKG3 вызывает процедуру из PKG1.

В. Как работает эта циклическая зависимость?
A. Это не циклическая зависимость ....

SQL> select name, type, referenced_name, referenced_type
  2  from user_dependencies
  3  where referenced_owner = user
  4  /

NAME            TYPE            REFERENCED_NAME REFERENCED_TYPE
--------------- --------------- --------------- ---------------
PKG1            PACKAGE BODY    PKG1            PACKAGE
PKG1            PACKAGE BODY    PKG2            PACKAGE
PKG2            PACKAGE BODY    PKG2            PACKAGE
PKG2            PACKAGE BODY    PKG3            PACKAGE
PKG3            PACKAGE BODY    PKG3            PACKAGE
PKG3            PACKAGE BODY    PKG1            PACKAGE

6 rows selected.

SQL> 

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

SQL> drop package pkg1
  2  /

Package dropped.

SQL> drop package pkg2
  2  /

Package dropped.

SQL> drop package pkg3
  2  /

Package dropped.

SQL>

Затем мы перестраиваем ...

SQL> create or replace package pkg3 is
  2      procedure p5;
  3      procedure p6;
  4  end pkg3;
  5  /

Package created.

SQL> create or replace package pkg2 is
  2      procedure p3;
  3      procedure p4;
  4  end pkg2;
  5  /

Package created.

SQL> create or replace package pkg1 is
  2      procedure p1;
  3      procedure p2;
  4  end pkg1;
  5  /

Package created.

SQL> create or replace package body pkg2 is
  2      procedure p3 is
  3      begin
  4          pkg3.p5;
  5      end p3;
  6      procedure p4 is
  7      begin
  8          dbms_output.put_line('PKG2.P4');
  9      end p4;
 10  end pkg2;
 11  /

Package body created.

SQL> create or replace package body pkg3 is
  2      procedure p5 is
  3      begin
  4          dbms_output.put_line('PKG3.P5');
  5      end p5;
  6      procedure p6 is
  7      begin
  8          pkg1.p1;
  9      end p6;
 10  end pkg3;
 11  /

Package body created.

SQL> create or replace package body pkg1 is
  2      procedure p1 is
  3      begin
  4          dbms_output.put_line('PKG1.P1');
  5      end p1;
  6      procedure p2 is
  7      begin
  8          pkg2.p4;
  9      end p2;
 10  end pkg1;
 11  /

Package body created.

SQL>

Порядок отдельных объектов не имеет значения. Просто создайте спецификации пакета перед телами пакетов. Хотя даже это на самом деле не имеет значения ...

SQL> create or replace package pkg4 is
  2      procedure p7;
  3  end pkg4;
  4  /

Package created.

SQL> create or replace package body pkg4 is
  2      procedure p7 is
  3      begin
  4          dbms_output.put_line('PKG4.P7::'||constants_pkg.whatever);
  5      end p7;
  6  end pkg4;
  7  /

Warning: Package Body created with compilation errors.

SQL> show errors
Errors for PACKAGE BODY PKG4:

LINE/COL ERROR
-------- -----------------------------------------------------------------
4/9      PL/SQL: Statement ignored
4/43     PLS-00201: identifier 'CONSTANTS_PKG.WHATEVER' must be declared
SQL>

PKG4 НЕВЕРНО, потому что мы еще не построили CONSTANTS_PKG .

SQL> create or replace package constants_pkg is
  2      whatever constant varchar2(20) := 'WHATEVER';
  3  end constants_pkg;
  4  /

Package created.

SQL> select object_name, object_type, status
  2  from user_objects
  3  where status != 'VALID'
  4  order by 1, 2
  5  /

OBJECT_NAME     OBJECT_TYPE     STATUS
--------------- --------------- -------
PKG4            PACKAGE BODY    INVALID

SQL> 
SQL> set serveroutput on size unlimited
SQL> exec pkg4.p7
PKG4.P7::WHATEVER

PL/SQL procedure successfully completed.

SQL> select object_name, object_type, status
  2  from user_objects
  3  where status != 'VALID'
  4  order by 1, 2
  5  /

no rows selected

SQL>

Все, что создано с использованием CREATE OR REPLACE , создается всегда, оно просто помечается как INVALID, если есть ошибки. Как только мы его выполняем, прямо или косвенно, база данных компилирует его для нас. Итак, порядок не имеет значения. На самом деле это не так.

Если вас беспокоит идея завершить сборку с недействительными объектами - и я немного симпатизирую этому, нам говорят не жить с разбитыми окнами - вы можете использовать скрипт utlrp или в 11g пакет UTL_RECOMP ; для любого подхода требуется учетная запись SYSDBA.

править 2

Процесс основан на инструменте сборки , который был построен поставщиком продукта, с которым мы интегрируемся, поэтому единственный входные данные, которые я могу передать процессу сборки, представляют собой список файлов в том порядке, в котором они должны быть встроены. Если есть ошибка компилятора , инструмент сборки не работает, нам нужно вручную отправить запрос на новую сборку .

Это политическая проблема, а не техническая. Это не означает, что политические проблемы не могут быть решены с помощью технического исправления, просто техническое исправление - не лучший инструмент для работы. Удачи.

8
ответ дан 7 December 2019 в 01:20
поделиться

Одна мелочь, на которую нужно обратить внимание, когда ходишь по дереву иждивенцев. Зависимости для некомпилированных программ не показывают...

SQL> drop package constants_pkg
  2  /

Package dropped.

SQL> create or replace package body pkg4 is
  2      procedure p7 is
  3      begin
  4          dbms_output.put_line('PKG4.P7::'||zzz_constants_pkg.whatever);
  5      end p7;
  6  end pkg4;
  7  /

Warning: Package Body created with compilation errors.

SQL> show errors
Errors for PACKAGE BODY PKG4:

LINE/COL ERROR
-------- -----------------------------------------------------------------
4/9      PL/SQL: Statement ignored
4/43     PLS-00201: identifier 'ZZZ_CONSTANTS_PKG.WHATEVER' must be
         declared

SQL>

Итак, тело для PKG4 является ИНВАЛИДНЫМ, потому что ZZZ_CONSTANTS_PKG не существует.

SQL> create or replace package zzz_constants_pkg is
  2      whatever constant varchar2(20) := 'WHATEVER';
  3  end zzz_constants_pkg;
  4  /

Package created.

SQL>

Но тело для PKG4 все еще INVALID, поэтому следующий запрос не возвращает его зависимость от ZZZ_CONSTANTS_PKG .....

SQL> select name, type, referenced_name, referenced_type
  2  from user_dependencies
  3  where referenced_owner = user
  4  /

NAME            TYPE            REFERENCED_NAME   REFERENCED_TYPE
--------------- --------------- ----------------- ---------------
PKG1            PACKAGE BODY    PKG1              PACKAGE
PKG1            PACKAGE BODY    PKG2              PACKAGE
PKG2            PACKAGE BODY    PKG2              PACKAGE
PKG2            PACKAGE BODY    PKG3              PACKAGE
PKG3            PACKAGE BODY    PKG3              PACKAGE
PKG3            PACKAGE BODY    PKG1              PACKAGE
PKG4            PACKAGE BODY    PKG4              PACKAGE

7 rows selected.

SQL>

Теперь скомпилируем PKG4 и повторно запросим зависимости .....

SQL> alter package pkg4 compile body;

Package body altered.

SQL> select name, type, referenced_name, referenced_type
  2  from user_dependencies
  3  where referenced_owner = user
  4  /

NAME            TYPE            REFERENCED_NAME   REFERENCED_TYPE
--------------- --------------- ----------------- ---------------
PKG1            PACKAGE BODY    PKG1              PACKAGE
PKG1            PACKAGE BODY    PKG2              PACKAGE
PKG2            PACKAGE BODY    PKG2              PACKAGE
PKG2            PACKAGE BODY    PKG3              PACKAGE
PKG3            PACKAGE BODY    PKG3              PACKAGE
PKG3            PACKAGE BODY    PKG1              PACKAGE
PKG4            PACKAGE BODY    PKG4              PACKAGE
PKG4            PACKAGE BODY    ZZZ_CONSTANTS_PKG PACKAGE

8 rows selected.

SQL> 
1
ответ дан 7 December 2019 в 01:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: