Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Làm thế nào để tìm các phụ thuộc bên trong một gói oracle?

Bạn có thể nhận được các cuộc gọi đến các thủ tục trong một gói với PL / Phạm vi, bắt đầu bằng:

alter session set plscope_settings = 'IDENTIFIERS:ALL';

Nếu sau đó bạn biên dịch lại gói của mình, hãy sử dụng một phác thảo đơn giản dựa trên mô tả của bạn ở đây:

create or replace package p42 as
  procedure a;
  procedure b;
  procedure c;
  procedure d;
  function f return number;
end p42;
/

create or replace package body p42 as

  procedure a is
  begin
    b;
    c;
  end a;

  procedure b is
    n number;
  begin
    n := f;
  end b;

  procedure c is
    n number;
  begin
    n := f;
  end c;

  procedure d is
  begin
    null;
  end d;

  function f return number is
  begin
    return 42;
  end f;
end p42;
/

thì bạn có thể xem các tham chiếu khác nhau trong user_identifiers lượt xem. Sử dụng ví dụ từ tài liệu để có được dàn ý:

WITH v AS (
  SELECT    Line,
            Col,
            INITCAP(NAME) Name,
            LOWER(TYPE)   Type,
            LOWER(USAGE)  Usage,
            USAGE_ID,
            USAGE_CONTEXT_ID
    FROM USER_IDENTIFIERS
      WHERE Object_Name = 'P42'
        AND Object_Type = 'PACKAGE BODY'
)
SELECT RPAD(LPAD(' ', 2*(Level-1)) ||
                 Name, 20, '.')||' '||
                 RPAD(Type, 20)||
                 RPAD(Usage, 20)
                 IDENTIFIER_USAGE_CONTEXTS
  FROM v
  START WITH USAGE_CONTEXT_ID = 0
  CONNECT BY PRIOR USAGE_ID = USAGE_CONTEXT_ID
  ORDER SIBLINGS BY Line, Col
/

IDENTIFIER_USAGE_CONTEXTS                                   
-------------------------------------------------------------
P42................. package             definition          
  A................. procedure           definition          
    B............... procedure           call                
    C............... procedure           call                
  B................. procedure           definition          
    N............... variable            declaration         
      Number........ number datatype     reference           
    N............... variable            assignment          
      F............. function            call                
  C................. procedure           definition          
    N............... variable            declaration         
      Number........ number datatype     reference           
    N............... variable            assignment          
      F............. function            call                
  D................. procedure           definition          
  F................. function            definition          
    Number.......... number datatype     reference           

Để đạt được điều gì đó gần hơn với những gì bạn muốn, bạn vẫn cần một truy vấn phân cấp để tìm tên của từng thủ tục / hàm gọi một thủ tục / hàm khác, vì bạn không quan tâm đến (ví dụ) các bước gán, chỉ nơi những điều đó đã xảy ra.

Như một điểm khởi đầu, bạn có thể làm:

select *
from (
  select name, type, connect_by_root(name) as root_name,
    connect_by_root(type) as root_type, connect_by_isleaf as isleaf
  from user_identifiers
  start with object_type = 'PACKAGE BODY'
  and object_name = 'P42'
  and type in ('FUNCTION', 'PROCEDURE')
  and usage = 'DEFINITION'
  connect by object_type = prior object_type
  and object_name = prior object_name
  and usage_context_id = prior usage_id
)
where type in ('FUNCTION', 'PROCEDURE');

NAME TYPE               ROOT_NAME ROOT_TYPE     ISLEAF
---- ------------------ --------- --------- ----------
A    PROCEDURE          A         PROCEDURE          0
B    PROCEDURE          A         PROCEDURE          1
C    PROCEDURE          A         PROCEDURE          1
B    PROCEDURE          B         PROCEDURE          0
F    FUNCTION           B         PROCEDURE          1
C    PROCEDURE          C         PROCEDURE          0
F    FUNCTION           C         PROCEDURE          1
D    PROCEDURE          D         PROCEDURE          1
F    FUNCTION           F         FUNCTION           0

sau đó lọc các nút lá và kết hợp các trình gọi:

select root_name, root_type,
  listagg(case when name = root_name then null else name end, ', ')
    within group (order by name) as callers
from (
  select name, type, connect_by_root(name) as root_name,
    connect_by_root(type) as root_type, connect_by_isleaf as isleaf
  from user_identifiers
  start with object_type = 'PACKAGE BODY'
  and object_name = 'P42'
  and type in ('FUNCTION', 'PROCEDURE')
  and usage = 'DEFINITION'
  connect by object_type = prior object_type
  and object_name = prior object_name
  and usage_context_id = prior usage_id
)
where type in ('FUNCTION', 'PROCEDURE')
and isleaf = 1
group by root_name, root_type;

ROOT_NAME ROOT_TYPE CALLERS            
--------- --------- --------------------
A         PROCEDURE B, C                
B         PROCEDURE F                   
C         PROCEDURE F                   
D         PROCEDURE                     

Nhưng điều đó không hiển thị F; bạn có thể thêm một liên kết bên ngoài để có được điều đó:

with ui as (
  select * from user_identifiers
  where object_type = 'PACKAGE BODY'
  and object_name = 'P42'
),
calls as (
  select object_type, object_name, name, type, signature,
    connect_by_root(name) as root_name,
    connect_by_root(type) as root_type,
    connect_by_root(signature) as root_signature,
    connect_by_isleaf as isleaf
  from ui
  start with type in ('FUNCTION', 'PROCEDURE')
  and usage = 'DEFINITION'
  connect by usage_context_id = prior usage_id
  and prior usage != 'CALL'
)
select ui.name, ui.type,
  listagg(case when c.name = c.root_name then null else c.name end, ', ')
    within group (order by c.name) as callers
from ui
left join calls c on c.object_type = ui.object_type
and c.object_name = ui.object_name
and c.root_type = ui.type
and c.root_name = ui.name
and c.root_signature = ui.signature
and c.type in ('FUNCTION', 'PROCEDURE')
and c.isleaf = 1
where ui.type in ('FUNCTION', 'PROCEDURE')
and ui.usage = 'DEFINITION'
group by ui.name, ui.type;

NAME TYPE               CALLERS            
---- ------------------ --------------------
A    PROCEDURE          B, C                
B    PROCEDURE          F                   
C    PROCEDURE          F                   
D    PROCEDURE                              
F    FUNCTION                               

Tôi khá chắc rằng điều đó có thể được đơn giản hóa ...

Lấy cờ chính / phụ / độc lập phức tạp hơn một chút; bạn cần phải quyết định ý nghĩa của từng thứ trong số đó (ví dụ:main có cuộc gọi đi nhưng không có cuộc gọi nào đến; độc lập không có cuộc gọi vào hoặc ra; phụ thuộc vào mọi thứ khác) có thể bằng cách tham gia thêm để tìm ra mọi thứ.

Vì vậy, đây là điểm khởi đầu cung cấp cho bạn một số thông tin và hy vọng chỉ ra những điều cần khám phá để nhận được tất cả thông tin bạn cần, ở định dạng bạn cần.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sử dụng mệnh đề IN với một chuỗi được phân tách bằng dấu phẩy từ đầu ra của một hàm Replace () trong Oracle SQL

  2. Tháng 7 năm 2016 PSU không tạo được isqora

  3. Làm cách nào để kiểm tra xem một cột có tồn tại hay không trước khi thêm nó vào bảng hiện có trong PL / SQL?

  4. Làm cách nào để thoát dấu phẩy và dấu ngoặc kép cùng một lúc cho tệp CSV?

  5. Sử dụng cơ sở dữ liệu Oracle với CakePHP 2.0