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

时间:2009-11-10 11:28:25

标签: oracle

我编写了以下查询以获取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;

5 个答案:

答案 0 :(得分:25)

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

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 :(得分:5)

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

如果要查看绑定变量的值,则应激活该会话的跟踪。您可以通过在该会话中执行以下命令来执行此操作:

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

有关AskTom: 10046 tracing

的更多信息

答案 2 :(得分: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'));

此方法显示仅显示peeked绑定变量。唯一可靠的方法是使用绑定变量跟踪

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

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

答案 3 :(得分:2)

运行以下查询,该查询将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;
/

答案 4 :(得分:0)

查看 BiPin 的回答,我对其进行了一些修改以满足我的需要。 我需要弄清楚用户在实时运行报告时使用了哪些参数。这是我的解决方案,它将 childnumber 添加到来自 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;