oracle中如何获取最后执行的SQL语句并绑定变量值

Posted

技术标签:

【中文标题】oracle中如何获取最后执行的SQL语句并绑定变量值【英文标题】:How to get the last executed SQL statement and bind variable values in oracle 【发布时间】:2009-11-10 11:28:24 【问题描述】:

我编写了以下查询来获取特定会话在 oracle 数据库中最后执行的 SQL 语句。 SQL 文本不包含绑定变量的实际值。如何获取绑定变量值以及 SQL 文本。

SELECT * FROM v$SQLTEXT_WITH_NEWLINES WHERE address = 
  (SELECT prev_sql_addr FROM v$session WHERE audsid = userenv('SESSIONID'))
ORDER BY piece;

【问题讨论】:

【参考方案1】:

要获取绑定变量,您必须使用下面的代码,您不需要使用跟踪。

SELECT * FROM v$sql_bind_capture WHERE sql_id='';

SELECT NAME,POSITION,DATATYPE_STRING,VALUE_STRING 
FROM v$sql_bind_capture WHERE sql_id='';

http://shaharear.blogspot.com/2009/02/find-bind-variable-value.html

【讨论】:

+1 download.oracle.com/docs/cd/B19306_01/server.102/b14237/… 但 STATISTICS_LEVEL 服务器初始化参数必须高于 BASIC。【参考方案2】:

我认为默认情况下不会存储绑定变量值。不考虑潜在的安全问题(查看其他会话的实际工作),要存储的数据量将是巨大的。

如果您想查看绑定变量的值,您应该激活该会话的跟踪。您可以通过在该会话中执行以下命令来做到这一点:

alter session set events '10046 trace name context forever, level 12'; 

更多关于AskTom: 10046 tracing的信息

【讨论】:

以后的版本(10g 和 11g)确实在 V$SQL_BIND_capture 中记录了用于 peeking 的绑定变量。但这仅适用于该 SQL 解析的优化阶段,而不是每次执行。 @GaryMyers 你能提供一个参考吗?【参考方案3】:

如果你在sqlplus你可以执行

select * from table ( dbms_xplan.display_cursor (null,null, 'ADVANCED'));

或者如果您正在寻找其他人执行的 SQL,只需输入他们的 SQL_ID 和子游标#:

select * from table ( dbms_xplan.display_cursor ('sql_id',child_cursor#, 'ADVANCED'));

select * from table ( dbms_xplan.display_cursor ('a18asdr99x',0, 'ADVANCED'));

这个方法只显示了被偷看的绑定变量。唯一可靠的方法是使用绑定变量进行跟踪

dbms_monitor.session_trace_enable(session_id => 127, serial_num => 29, waits => FALSE, binds => TRUE)

当然,这必须在查询执行之前完成

【讨论】:

【参考方案4】:

运行以下查询,该查询将 sql_id 作为输入参数,并将使用替换的绑定变量值给出输出。

set serveroutput on;


DECLARE
   v_fulltext   CLOB;
   v_sql_id     VARCHAR2 (100);

   CURSOR c1( v_sql_id varchar2)
   IS
      SELECT decode(substr(NAME,1,4),':SYS',replace(name,':',':"')||'"' ,NAME ) NAME, POSITION, datatype_string,nvl(VALUE_STRING,'NULL') value_string
    FROM v$sql_bind_capture
       WHERE sql_id = v_sql_id;
BEGIN

  v_sql_id:= '&sql_id';

   SELECT sql_fulltext
     INTO v_fulltext
     FROM v$sql
    WHERE sql_id =v_sql_id  AND ROWNUM = 1;

   FOR rec IN c1(v_sql_id)
   LOOP


      IF substr(rec.datatype_string,1,8) = 'VARCHAR2'
      THEN
     SELECT REPLACE (v_fulltext,
             rec.NAME,
             '''' || rec.value_string || ''''
            )
       INTO v_fulltext
       FROM DUAL;
      END IF;

      IF rec.datatype_string = 'NUMBER'
      THEN
     SELECT REPLACE (v_fulltext, rec.NAME, rec.value_string)
       INTO v_fulltext
       FROM DUAL;
      END IF;

   END LOOP;
   DBMS_OUTPUT.PUT_LINE(v_fulltext);

   EXCEPTION
   WHEN NO_DATA_FOUND
   THEN DBMS_OUTPUT.PUT_LINE('NO SQL FOUND FOR THE SQL ID');

END;
/

【讨论】:

这对我不起作用 - 最后一个绑定变量没有被替换。【参考方案5】:

查看 BiPin 的答案,我对其进行了一些修改以满足我的需要。 我需要弄清楚用户在实时运行报告时使用了哪些参数。这是我的解决方案,它将子编号添加到 v$sql_bind_capture 的查询中。

declare
v_sql_id varchar(100);
v_fulltext clob;
v_childnumber number;
begin
v_sql_id := '&sql_id';
v_childnumber := '&childnumber';
SELECT LISTAGG(SQL_text, '') within group (order by piece) 
     INTO v_fulltext
     FROM v$sqltext
    WHERE sql_id =v_sql_id;      
    for I in (select name,VALUE_STRING from v$sql_bind_capture where sql_id = V_SQL_ID and child_number = V_CHILDNUMBER)LOOP
        v_fulltext := regexp_replace(v_fulltext,i.name||' ',i.value_string);
      end LOOP;
      DBMS_OUTPUT.PUT_LINE(v_fulltext);
end;

【讨论】:

以上是关于oracle中如何获取最后执行的SQL语句并绑定变量值的主要内容,如果未能解决你的问题,请参考以下文章

如何获取Oracle数据库中sql语句的执行时间

Oracle 优化器自适应游标共享(Adaptive Cursor Sharing)功能

Oracle绑定变量

oracle如何执行多条create 语句

oracle中SQL的缓存

Oracle 自适应游标