Oracle - 从 sql 文本中获取 table 名称
Oracle - get table name from sql text
我在 table 中有一列包含简单的 sql 查询,我想从中 regexp_substr table 名称。
文本示例:
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
或
SELECT DISTINCT QRMPT_PRODUCT VALUE, QRMPT_PRODUCT LABEL FROM
DWH_OWNER.DWH_QRM_PRODUCT_TYPES ORDER BY VALUE
所以,我需要找到 "FROM",跳过一些空格然后得到第一个词。
我暂时对第二个 table.
不感兴趣
我做了什么:
select
sql,
regexp_substr(upper(sql), '(\s)FROM(\s)*([[:alnum:]]|\.|_)*') tablename
from my_table_with_queries;
输出:
FROM DWH_OWNER.DWH_ACCOUNTS
FROM
DWH_OWNER.DWH_QRM_PRODUCT_TYPES
我的查询有什么问题:
它输出 table 名称,在 table 名称之前带有 "FROM "。我想要直接 table 名称,没有空格。
期望的输出:
DWH_OWNER.DWH_ACCOUNTS
DWH_OWNER.DWH_QRM_PRODUCT_TYPES
编辑:
我设法在上一步中完成 regexp_substr(tablename, '(\w|_|\.)+', 1,2)
来清理 tablename。但是是否可以使用单个正则表达式获得所需的输出?
Here 应该是一个 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;
与其尝试编写自己的解析器,不如让 Oracle 通过 explain plan
为您解析它,然后查看计划 table 以了解它引用了哪些对象:
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
正如@Aleksej 所建议的,如果优化器仅使用索引(因此执行计划显示索引 access/scan 而没有命中 table,因为所有相关列都在索引中)然后plan table 只报告索引。您可以通过加入索引视图来实现这一点;如果它也达到了 table,它只会报告两者:
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');
您还需要在每次解释计划调用和查询之前确保计划 table 为空以避免混淆,或者设置一个语句 ID 以便您可以识别哪些 table 与该计划相关当前查询。
我在 table 中有一列包含简单的 sql 查询,我想从中 regexp_substr table 名称。 文本示例:
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
或
SELECT DISTINCT QRMPT_PRODUCT VALUE, QRMPT_PRODUCT LABEL FROM
DWH_OWNER.DWH_QRM_PRODUCT_TYPES ORDER BY VALUE
所以,我需要找到 "FROM",跳过一些空格然后得到第一个词。 我暂时对第二个 table.
不感兴趣我做了什么:
select
sql,
regexp_substr(upper(sql), '(\s)FROM(\s)*([[:alnum:]]|\.|_)*') tablename
from my_table_with_queries;
输出:
FROM DWH_OWNER.DWH_ACCOUNTS
FROM
DWH_OWNER.DWH_QRM_PRODUCT_TYPES
我的查询有什么问题: 它输出 table 名称,在 table 名称之前带有 "FROM "。我想要直接 table 名称,没有空格。
期望的输出:
DWH_OWNER.DWH_ACCOUNTS
DWH_OWNER.DWH_QRM_PRODUCT_TYPES
编辑:
我设法在上一步中完成 regexp_substr(tablename, '(\w|_|\.)+', 1,2)
来清理 tablename。但是是否可以使用单个正则表达式获得所需的输出?
Here 应该是一个 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;
与其尝试编写自己的解析器,不如让 Oracle 通过 explain plan
为您解析它,然后查看计划 table 以了解它引用了哪些对象:
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
正如@Aleksej 所建议的,如果优化器仅使用索引(因此执行计划显示索引 access/scan 而没有命中 table,因为所有相关列都在索引中)然后plan table 只报告索引。您可以通过加入索引视图来实现这一点;如果它也达到了 table,它只会报告两者:
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');
您还需要在每次解释计划调用和查询之前确保计划 table 为空以避免混淆,或者设置一个语句 ID 以便您可以识别哪些 table 与该计划相关当前查询。