沒有可靠的方法來識別調用PL/SQL對象的SQL。
下面是識別調用SQL的不太穩健的方法。我以前使用過這樣的代碼,但只有在我知道PL/SQL永遠不會同時運行的特殊情況下。
這個好像是就好像應該那麼簡單。數據字典跟蹤所有會話並運行SQL。您可以使用sys_context('userenv', 'sid')
找到當前會話,將其與GV$SESSION
匹配,然後獲得SQL_ID
和PREV_SQL_ID
。但這些都不包含調用SQL。 SYS_CONTEXT
中甚至有CURRENT_SQL
,但它僅用於細粒度審計。
相反,調用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非常困難,除非您可以確保每個人始終遵循嚴格的語法規則。
我不願意支持這樣的事情。如果查詢位於存儲過程中,則可以檢查調用堆棧並使用數據字典查找代碼中的查詢。您可能能夠獲取當前會話的sql_id並查詢查詢文本,但我不會認爲這將適用於各個版本。我認爲如果你想改變行爲,讓函數接受一個額外的參數會更有意義。 –
如果你真的確定了,你可以使用高級重寫來讓一個任意的查詢實際執行一個完全不同的查詢https://oracle-base.com/articles/10g/dbms_advanced_rewrite我會非常明智地做這樣的事情,但是,因爲它使調試系統變得「有趣」。 –
謝謝Justin。這非常有用。唯一的問題是,我似乎必須事先知道請求的查詢是什麼。希望以某種方式查看該查詢的文本。再次感謝。 –