首先,我想说清楚问题与物化视图功能无关。
假设我有一个表函数,它返回一组预定义的列。
当函数调用提交为
时SELECT col1, col2, col3
FROM TABLE(my_tfn(:p1))
WHERE col4 = 'X';
我可以评估参数并选择要执行的查询。 我可以打开一个预定义的游标,也可以动态组合我的查询。
如果不是评估参数,而是要评估请求查询的文本,该怎么办?
例如,如果我的函数返回20列,但查询只请求4, 我可以为返回类型的其余16个列分配NULL,并执行更少的连接。 或者我可以将过滤器推送到我的动态查询。
有没有办法让这种情况发生? 更一般地说,有没有办法在退出函数之前查看请求查询?
答案 0 :(得分:2)
没有可靠的方法来识别调用PL / SQL对象的SQL。
下面是一种识别调用SQL的不太强大的方法。我之前使用过这样的代码,但只有在我知道PL / SQL永远不会同时运行的特殊情况下。
这个似乎就像它应该如此简单。数据字典跟踪所有会话并运行SQL。您可以使用sys_context('userenv', 'sid')
找到当前会话,将其与GV$SESSION
相匹配,然后获取SQL_ID
和PREV_SQL_ID
。但这些都不包含调用SQL。 CURRENT_SQL
中只有SYS_CONTEXT
,但它只适用于细粒度的审核。
相反,必须通过字符串搜索找到调用SQL。使用PL / SQL对象的唯一名称将有助于过滤掉不相关的语句。为防止重新运行旧语句,必须在找到SQL后立即从共享池中单独清除SQL。这可能会导致竞争条件,因此这种方法只有在从未被同时调用时才会起作用。
--Create simple test type for function.
create or replace type clob_table is table of clob;
--Table function that returns the SQL that called it.
--This requires elevated privileges to run.
--To simplify the code, run this as SYS:
-- "grant execute on sys.dbms_shared_pool to your_user;"
--(If you don't want to do that, convert this to invoker's rights and use dynamic SQL.)
create or replace function my_tfn return clob_table is
v_my_type clob_table;
type string_table is table of varchar2(4000);
v_addresses string_table;
v_hash_values string_table;
begin
--Get calling SQL based on the SQL text.
select sql_fulltext, address, hash_value
bulk collect into v_my_type, v_addresses, v_hash_values
from gv$sql
--Make sure there is something unique in the query.
where sql_fulltext like '%my_tfn%'
--But don't include this query!
--(Normally creating a quine is a challenge, but in V$SQL it's more of
-- a challenge to avoid quines.)
and sql_fulltext not like '%quine%';
--Flush the SQL statements immediately, so they won't show up in next run.
for i in 1 .. v_addresses.count loop
sys.dbms_shared_pool.purge(v_addresses(i)||', '||v_hash_values(i), 'C');
end loop;
--Return the SQL statement(s).
return v_my_type;
end;
/
现在这样的查询会自行返回,证明PL / SQL代码正在读取调用它的SQL:
SELECT * FROM TABLE(my_tfn) where 1=1;
SELECT * FROM TABLE(my_tfn) where 2=2;
但即使你经历了所有这些麻烦 - 你将如何处理结果呢?除非你能确保每个人都遵循严格的语法规则,否则解析SQL是非常困难的。