create or replace function myProc(p_id number) return varchar2 is
v_sql_id varchar2(13);
v_table_name varchar2(100);
begin
--Get the SQL used to call this function
select sql_id into v_sql_id
from v$sql
where lower(sql_text) like 'select myproc(id)%'
and users_executing > 0;
--Get the table name
select object_name into v_table_name
from v$sql_plan
where sql_id = v_sql_id
and operation = 'TABLE ACCESS';
--For testing, return the table name.
return v_table_name;
end;
/
create table test1(id number);
create table test2(id number);
insert into test1 values(1);
insert into test2 values(2);
commit;
--Returns TEST1 (careful, your IDE may add this comment to the SQL!)
select MyProc(id) from test1;
--Returns TEST2
select MyProc(id) from test2;
Идея состоит в том, чтобы найти исполняемый в настоящий момент SQL, а затем найти таблицу, используемую этим SQL.Но есть много потенциальных проблем.
Получение SQL_ID
Есть много способов найти SQL_ID, но ни один из них не работает хорошо.Вот подходы, которые я попробовал, может быть, кто-то может выяснить, как заставить один из них работать лучше.
Например, в v $ session SQL_ID будет ссылаться на себя, а PREV_SQL_ID ссылается на некоторый бесполезный запрос транзакции (по крайней мере, в моей системе).
select sql_id, prev_sql_id from v$session where sid = sys_context('USERENV', 'SID');
Поиск запроса в v $ sql и упорядочение LAST_LOAD_TIME не всегда работает, LAST_LOAD_TIME не всегда обновляется.
select sql_id from v$sql
where lower(sql_text) like 'select myproc(id)%'
order by last_load_time desc;
ИспользованиеSQL_TEXT и USERS_EXECUTING> 0 будут работать, но только если только один сеанс одновременно выполняет этот запрос.И искать такой текст очень опасно.Некоторые среды могут помещать текст перед выбором, например, пробелы или комментарии.Но вы не можете искать «% select ...», потому что тогда запрос вернется сам.
select sql_id into v_sql_id
from v$sql
where lower(sql_text) like 'select myproc(id)%'
and users_executing > 0;
Поиск таблицы
С помощью SQL_ID мыможет легко получить текст запроса из v $ sql.sql_text или v $ sql.sql_fulltext. может быть возможным для вас, чтобы проанализировать этот запрос, но в целом я бы рекомендовал вам не разбирать SQL.Это гораздо сложнее, чем думает большинство людей.Если вы абсолютно уверены, что будет использоваться только конкретный простой запрос, то, возможно, этот подход будет работать.
Более реалистичный подход, вероятно, заключается в использовании v $ sql_plan для поиска используемых таблиц.Это будет работать для вашего запроса, но вам придется выполнять больше работы, если в вашем запросе может быть несколько таблиц, или если есть представления или индексы (вам нужно присоединиться к user_index, чтобы найти фактическую таблицу),и т. д.
select object_name
from v$sql_plan
where sql_id = <SQL_ID>
and operation = 'TABLE ACCESS'
Возможно, вам потребуется предоставить пользователю select для v_ $ sql и v_ $ sql_plan.Ох, и это будет очень медленно.Идея @ Иолсона о передаче имени таблицы в качестве параметра намного лучше, если она работает.