如何获取整个数据库中某列使用的函数名?

How to get the functions name used by a column in the whole database?

我有一个名为 employee_vw 的视图,其中包含以下查询:

select function_standard(ename) from employees; 

我想知道列上应用了哪些函数。我尝试使用 select dbms_metadata.get_ddl('COLUMN','ENAME','HR') FROM DUAL,但没有看到列对象类型。

我的要求是能够列出整个数据库中应用于指定列的所有函数。有什么办法可以找出来吗?

提前致谢。

概览

您正在为调查视图 (employee_vw) 的每个列定义术语寻找以下类型的信息:

  1. 列定义术语与系统中任何函数之间的依赖关系
  2. 列定义项与任意基列的依赖关系view/table

据我所知,数据字典不维护列级别的依赖项。但是可以查询tables/views和函数之间的列目录和依赖关系。使用此信息,可以估算出所需的结果。

三种信息被利用:

  1. 调查视图 (employee_vw) 和任何函数之间的依赖关系。
  2. 调查视图 (employee_vw) 及其基础 table 和视图之间的依赖关系
  3. 已调查视图 (employee_vw) 的列定义项中出现基本 table/view 列。

前两种数据可通过dba_dependencies系统查看。 对于最后一项,基础 tables/views 中的所有列名都与视图定义文本匹配,限制任何列名的出现,使其前面必须有任何引用函数的名称。

查询

下面的查询实现了上面的想法:

  SELECT fndep.referenced_name  function_name
       , tcol.column_name       column_name
       , tcol.table_name        container_name
    FROM dba_dependencies fndep
    JOIN dba_dependencies tabdep   ON (tabdep.name = fndep.name AND tabdep.type = fndep.type)
    JOIN all_views        v        ON v.view_name = fndep.name 
    JOIN all_tab_cols     tcol     ON (tcol.table_name = tabdep.referenced_name)
   WHERE fndep.referenced_type  = 'FUNCTION'
     AND fndep.type             = 'VIEW'
     AND fndep.name             = UPPER('employee_vw')
     AND tabdep.referenced_type IN ( 'TABLE', 'VIEW' )
     AND lower(v.text_vc) LIKE lower('%'||fndep.referenced_name||'%'||tcol.column_name||'%')
       ;

基础tables/views实际上可能是同义词。以下查询满足这种情况:

  SELECT fndep.referenced_name  function_name
       , tcol.column_name       column_name
       , tcol.table_name        container_name
    FROM dba_dependencies fndep
    JOIN dba_dependencies tabsyndep   ON (tabsyndep.name = fndep.name AND tabsyndep.type = fndep.type)
    JOIN dba_synonyms     syn         ON (syn.synonym_name = tabsyndep.referenced_name)
    JOIN dba_tab_cols     tcol        ON (tcol.table_name = syn.table_name)
    JOIN dba_views        v           ON v.view_name = fndep.name 
   WHERE fndep.referenced_type  = 'FUNCTION'
     AND fndep.type             = 'VIEW'
     AND fndep.name             = UPPER('employee_vw')
     AND tabsyndep.referenced_type IN ( 'SYNONYM' )
     AND lower(v.text_vc) LIKE lower('%'||fndep.referenced_name||'%'||tcol.column_name||'%')
       ;

请注意,来自 plsql 包的函数可以应用于列定义中。如果需要考虑到这一点,在where条件中使用fndep.referenced_type IN ( 'FUNCTION', 'PACKAGE' )

注意事项

解决方案是一个近似值,但(至少)存在以下不足:

  • 引用函数和基础 table/view 列的名称可能出现在不同的列定义术语中。 (误报)
  • 引用函数的名称和基础 table/view 列可能出现在字符串文字中。 (误报)
  • 通过 dba_views.text_vc 可用的视图定义文本限制为 4000 个字符。然而,实际定义的长度可能长达 32767 个字符。后一种情况可以通过检查视图定义长度来检测。完整的文本也在 dba_views.text 列中可用,不幸的是数据类型 long 无法轻松操作。 (漏报;边缘情况下的误报)

如果您的视图定义超过 4000 的长度,您最好在临时 table 中复制调查视图的 dba_views 记录,将 text 替换为等效的clob 列。可以使用 to_lob. Beware of the intricacies sketched in this article.

完成转换

我不知道如何在不求助于成熟的 sql 解析的情况下规避其他警告。