Oracle - 从sql文本中获取表名

Flo*_*ita 3 regex oracle regexp-substr

我在一个表中有一个简单的SQL查询列,我想从它们regexp_substr表名.文本示例:

SELECT PT.PT_PARTY_NAME VALUE,PT.PT_PARTY_NAME LABEL
    FROM DWH_OWNER.DWH_ACCOUNTS ACC,
         DWH_OWNER.DWH_PARTIES PT
   WHERE ACC.ACC_SOURCE_ID = :P_DOMVAL_REF1
    AND ACC.ACC_PT_KEY = PT.PT_KEY
Run Code Online (Sandbox Code Playgroud)

要么

SELECT DISTINCT QRMPT_PRODUCT VALUE, QRMPT_PRODUCT LABEL FROM   
DWH_OWNER.DWH_QRM_PRODUCT_TYPES ORDER BY VALUE
Run Code Online (Sandbox Code Playgroud)

所以,我需要找到"FROM",跳过一些空格然后得到第一个单词.我对第二张表中的那一刻不感兴趣.

我做了什么:

select 
    sql, 
    regexp_substr(upper(sql), '(\s)FROM(\s)*([[:alnum:]]|\.|_)*') tablename
from my_table_with_queries;
Run Code Online (Sandbox Code Playgroud)

输出:

 FROM DWH_OWNER.DWH_ACCOUNTS
FROM   
    DWH_OWNER.DWH_QRM_PRODUCT_TYPES
Run Code Online (Sandbox Code Playgroud)

我的qyery有什么问题:它在表名之前输出带有"FROM"的表名.我想直接使用表名,没有空格.

期望的输出:

DWH_OWNER.DWH_ACCOUNTS
DWH_OWNER.DWH_QRM_PRODUCT_TYPES
Run Code Online (Sandbox Code Playgroud)

编辑: 我设法做regexp_substr(tablename, '(\w|_|\.)+', 1,2)了上一步做tablename干净.但是有可能通过一个正则表达式获得所需的输出?

应该是一个sqlfiddle,但该网站在这一刻不起作用.查询:

  with a as (
select 'SELECT PT.PT_PARTY_NAME VALUE,PT.PT_PARTY_NAME LABEL
    FROM DWH_OWNER.DWH_ACCOUNTS ACC,
         DWH_OWNER.DWH_PARTIES PT
   WHERE ACC.ACC_SOURCE_ID = :P_DOMVAL_REF1
    AND ACC.ACC_PT_KEY = PT.PT_KEY' sql from dual
 union all

 select 'SELECT DISTINCT QRMPT_PRODUCT VALUE, QRMPT_PRODUCT LABEL FROM   
DWH_OWNER.DWH_QRM_PRODUCT_TYPES ORDER BY VALUE' from dual
  )

select 
       regexp_substr(upper(sql), '\sFROM\s*(\w|\.|_)*') tablename, sql
from a;
Run Code Online (Sandbox Code Playgroud)

Ale*_*ole 7

您可以让Oracle为您解析它,而不是尝试编写自己的解析器,explain plan然后查看计划表以查看它引用的对象:

declare
  text varchar2(4000) := 'SELECT PT.PT_PARTY_NAME VALUE,PT.PT_PARTY_NAME LABEL
    FROM DWH_OWNER.DWH_ACCOUNTS ACC,
         DWH_OWNER.DWH_PARTIES PT
   WHERE ACC.ACC_SOURCE_ID = :P_DOMVAL_REF1
    AND ACC.ACC_PT_KEY = PT.PT_KEY';
begin
  execute immediate 'explain plan for ' || text;
end;
/

select distinct object_owner, object_name
from plan_table
where object_type = 'TABLE';

OBJECT_OWNER                   OBJECT_NAME                  
------------------------------ ------------------------------
DWH_OWNER                      DWH_ACCOUNTS                  
DWH_OWNER                      DWH_PARTIES                   
Run Code Online (Sandbox Code Playgroud)

作为@Aleksej建议,如果优化器仅使用一个索引(所以执行计划显示索引访问/扫描没有击中表,因为所有的相关列在索引中),那么该计划表只报告索引.你可以通过加入索引视图来允许它; 如果它也击中了表格,它只会报告两者:

select distinct case when pt.object_type = 'INDEX' then ai.table_owner
    else pt.object_owner end as owner,
  case when pt.object_type = 'INDEX' then ai.table_name
    else pt.object_name end as table_name
from plan_table pt
left join all_indexes ai on ai.owner = pt.object_owner
and ai.index_name = pt.object_name
where pt.object_type in ('TABLE', 'INDEX');
Run Code Online (Sandbox Code Playgroud)

您还需要在每个解释计划调用和查询之前确保计划表为空以避免混淆,或者设置语句ID以便您可以识别与当前查询相关的表.