【问题标题】:How to find the tables affected in a PL SQL package?如何在 PL SQL 包中找到受影响的表?
【发布时间】:2019-04-02 12:01:10
【问题描述】:

我必须找出在我现有的 PL SQL 包中发生插入或更新的表的列表。我开始分析包裹。问题是包代码运行在数千行代码中 调用许多其他包。另外,代码不是我写的。我无法运行 AWR 报告,因为它是开发环境。

有没有办法在启动事务后获取插入/更新发生的表? 可以编写触发器以满足我的要求吗?

【问题讨论】:

    标签: sql oracle stored-procedures plsql


    【解决方案1】:
    -- plain
    select *
    from dba_dependencies
    where name = 'PACKAGE_NAME' and owner = 'PACKAGE_OWNER'
    and type in ('PACKAGE', 'PACKAGE BODY') and referenced_type = 'TABLE';
    
    -- hierarchy
    select distinct referenced_owner, referenced_name, referenced_type, referenced_link_name
    from dba_dependencies
    where referenced_type = 'TABLE'
    start with name = 'PACKAGE_NAME' and owner = 'PACKAGE_OWNER' 
    and type in ('PACKAGE', 'PACKAGE BODY')
    connect by nocycle prior referenced_name = name and prior referenced_owner = owner
    and replace(prior referenced_type, 'PACKAGE BODY', 'PACKAGE') = replace(type, 'PACKAGE BODY', 'PACKAGE')
    and referenced_owner not in ('SYS', 'SYSTEM', 'OUTLN' , 'AUDSYS')
    order by 1, 2, 3;
    

    【讨论】:

    • 我不会说你的回答没有帮助。但是,正如我所说,一个包调用另一个包,这样深度太高了。所以,我应该继续在上面的查询中输入包名。
    • 我会尝试是否可以增强您的查询以列出所有引用包中的表。
    • 请记住,如果 PL/SQL 使用动态 SQL,SQL 嵌入在字符串变量中并在执行时运行,这些字符串 SQL 变量中的表将不会显示为依赖项,因为编译器永远不会看到它们.
    【解决方案2】:

    @akk0rd87 有更好的答案——DBA_DEPENDENCIES,用CONNECT BY 来获取被调用过程的表使用情况。

    他的答案唯一找不到的是由于动态 SQL 直接使用的表(例如,EXECUTE IMMEDIATE)。为此,您可以使用细粒度审计。

    对我来说,这种方法只是您遵循 @akk0rd87 的建议后的一种备份。

    由于 SO 不是免费的代码编写服务,我只给你粗略的介绍。

    1) 创建一个表作为您的审计跟踪。确保它至少具有以下列:

    • SCHEMA_NAME(30 个字符)
    • TABLE_NAME(30 个字符)
    • CALL_STACK(4000 个字符)
    • SQL_STMT(4000 个字符)

    2) 创建一个包作为审计处理程序。我为此提供代码,因为它必须遵循我提供的确切 API 才能用于细粒度审计。

    CREATE OR REPLACE PACKAGE BODY xxcust_table_access_aud_pkg AS
      PROCEDURE audit_access ( schema_name VARCHAR2, table_Name VARCHAR2, policy_name VARCHAR2 ) IS
      BEGIN
        INSERT INTO your_audit_table ( SCHEMA_NAME, TABLE_NAME, CALL_STACK, SQL_STMT )
        VALUES ( schema_name, 
                 table_Name,
                 substr(DBMS_UTILITY.format_call_stack,1,4000),
                 substr(SYS_CONTEXT ('userenv', 'CURRENT_SQL'),1,4000)
                )
      EXCEPTION
        WHEN others THEN 
          null;
      END;
    
    END xxcust_table_access_aud_pkg ;
    

    3) 遍历应用程序模式中的所有表,并为每个表调用DBMS_FGA.ADD_POLICY。例如,

    FOR r IN ( ... all my tables ... ) LOOP
      DBMS_FGA.add_policy(object_schema=> r.owner,
                          object_name => r.table_name,
                          policy_Name => -- make up something unique, maybe table_name plus some number,
                          audit_condition => '1=1',
                          audit_column => null,
                          handler_schema => -- your schema,
                          handler_module => 'XXCUST_TABLE_ACCESS_AUD_PKG', -- the package above
                          enable => true);
    

    4) 运行您的程序包并检查结果表

    5) 重复第 3 步,但删除策略而不是添加它们。

    【讨论】:

      【解决方案3】:

      不确定触发器是否可以成为解决方案,以下可能是解决方案之一,不过需要一些手动操作:

      1. 对主包执行 grep 以查找其他包名称,记下所有包的名称,包括主包。
      2. 从“all_source”表中获取所有这些包的源代码,在“NAME”属性上使用 where 子句并指定上面标识的包名称。
      3. 将上述软件包的源代码假脱机到一个文本文件中,并对插入和更新命令执行 grep。

      【讨论】:

        猜你喜欢
        • 2010-10-26
        • 2011-10-28
        • 2021-04-29
        • 1970-01-01
        • 1970-01-01
        • 2021-12-28
        • 1970-01-01
        • 2015-08-06
        • 1970-01-01
        相关资源
        最近更新 更多