Oracle pl / sql - 从dbms_sql中检索sql_id

时间:2014-02-04 22:17:24

标签: sql oracle plsql

使用dbms_sql.execute,是否可以以编程方式检索正在执行的查询的sql_id?

这是我失败的尝试:

declare
  v_sql_text varchar2(128) := 'select 123 from dual';
  v_cursor INTEGER;
  v_ret number;

  v_sql_id varchar2(13) := null;
BEGIN
  v_cursor := dbms_sql.open_cursor;
  dbms_sql.parse(v_cursor, v_sql_text, dbms_sql.native);   

  -- ==================================================
  -- attempt 1 - after parse
  select prev_sql_id
    into v_sql_id
    from v$session
    where audsid = sys_context('userenv', 'sessionid');

  dbms_output.put_line('after parse: ' || v_sql_id);
  -- ==================================================

  v_ret := dbms_sql.execute(v_cursor);

  -- ==================================================
  -- attempt 2 - after execute - this doesn't seem to work either
  --select prev_sql_id
  --  into v_sql_id
  --  from v$session
  --  where audsid = sys_context('userenv', 'sessionid');

  --dbms_output.put_line('after execute: ' || v_sql_id);
  -- ==================================================

  dbms_sql.close_cursor(v_cursor);
END;
/

1)这甚至可能吗?

2)有更好的方法吗?

其他资讯 - 2014年2月17日

我真的在sql_id child_number之后。

我们使用dbms_scheduler和dbms_sql的组合来“在后台”运行报告。我的目的是捕获并存储两条信息 - sql_id和child_number - 每次运行报告。我想捕获此信息以用于诊断目的(例如 - 可以使用dbms_xplan.display_cursor(sql_id,sql_child)显示运行的特定查询的缓存执行计划)。这样我们就不会依赖企业管理器,也不会将查询文本复制/粘贴到sqlplus中以查看计划[并且很可能最终会得到一个硬解析和可能不同的计划]。

增加复杂性的一件事是我们使用绑定变量。对于相同的sql_id,根据绑定变量偷看/直方图,可能存在许多不同的“子计划”。出于这个原因,我对直接查询v $ sql以获取此信息犹豫不决。我宁愿尝试使用v $ session,dbms_sql或其他一些Tom Kyte风格的巫术找到某种硬链接。

2014年2月21日更新

根据以下来源的信息处理解决方案:

https://dba.stackexchange.com/questions/55609/how-to-use-the-dbms-sql-to-get-the-analyze-for-insert-into-statement http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:40832696008013

我会在清理后发布一个简洁的例子。谢谢你的回复。

1 个答案:

答案 0 :(得分:2)

这适合我。

declare
  v_sql_text varchar2(128) := 'select 112233 from dual';
  v_cursor INTEGER;
  v_ret number;

  v_sql_id varchar2(13) := null;
BEGIN
  v_cursor := dbms_sql.open_cursor;
  dbms_sql.parse(v_cursor, v_sql_text, dbms_sql.native);   
  v_ret := dbms_sql.execute(v_cursor);
  dbms_sql.close_cursor(v_cursor);

  --To save time lets only look 5 minutes back
  --last_load_time is a varchar that's why we have to use to_date
  select sql_id into v_sql_id from v$sql
  where dbms_lob.compare(sql_fulltext, v_sql_text) = 0
  and to_date(last_load_time,'YYYY-MM-DD/HH24:MI:SS') > sysdate - (5/1440);

  dbms_output.put_line('v_sql_id: ' || v_sql_id);

END;
/