本文总结一下ORACLE数据库中如何获取SQL绑定变量值的方法,在SQL优化调优过程中,经常会用到这方面的知识点。在此梳理、总结一下,方面日后查找、翻阅。

方法1:查询V$SQL

V$SQL视图中的BIND_DATA字段用来存储绑定变量的值,但是从这个视图查询绑定变量的值,有很大的局限性:

1: 它的记录频率受_cursor_bind_capture_interval隐含参数控制,默认值为900,表示每900秒记录一次绑定值,也就是说在900内,绑定变量值的改变不会反应在这个视图中。除非你调整隐含参数_cursor_bind_capture_interval

2: 它记录的仅仅最后一次捕获的绑定变量值。

3: BIND_DATA数据类型为RAW,需要进行转换。

可以使用下面两种方式来查看绑定变量的值。

COL SQL_ID FOR A14;

COL SQL_TEXT FOR A32;

COL HASH_VALUE FOR 99999999999;

COL BIND_DATA FOR A32;

SELECT SQL_ID          

      ,SQL_TEXT

      ,LITERAL_HASH_VALUE

      ,HASH_VALUE

      ,DBMS_SQLTUNE.EXTRACT_BINDS(BIND_DATA) BIND_DATA

FROM V$SQL

WHERE SQL_TEXT LIKE ''SELECT * FROM TEST%';

 

 

COL SQL_ID FOR A14;

COL SQL_TEXT FOR A32;

COL HASH_VALUE FOR 99999999999;

COL BIND_DATA FOR A32;

SELECT SQL_ID          

      ,SQL_TEXT

      ,LITERAL_HASH_VALUE

      ,HASH_VALUE

      ,DBMS_SQLTUNE.EXTRACT_BIND(BIND_DATA,1).VALUE_STRING BIND_DATA

FROM V$SQL

WHERE SQL_TEXT LIKE 'SELECT * FROM TEST%';

如下实验所示,我们在一个会话中使用绑定变量的查询SQL语句,然后,我们来尝试获取绑定变量的值,如下所示:

SQL> SHOW USER;

USER is "TEST"

SQL> DESC TEST;

 Name                                      Null?    Type

 ----------------------------------------- -------- ----------------------------

 ID                                                 NUMBER(10)

 NAME                                               VARCHAR2(32)

 

SQL> 

SQL> VARIABLE NAME NVARCHAR2(32);

SQL> EXEC :NAME :='KKKK';

 

PL/SQL procedure successfully completed.

 

SQL> SELECT * FROM TEST WHERE NAME=:NAME;

 

no rows selected

 

SQL> 

 

 

 

SQL>SHOW USER;

USER is "SYS"

SQL> COL SQL_ID FOR A14;

SQL> COL SQL_TEXT FOR A32;

SQL> COL HASH_VALUE FOR 99999999999;

SQL> COL BIND_DATA FOR A32;

SQL> SELECT SQL_ID          

  2        ,SQL_TEXT

  3        ,LITERAL_HASH_VALUE

  4        ,HASH_VALUE

  5        ,DBMS_SQLTUNE.EXTRACT_BINDS(BIND_DATA) BIND_DATA

  6  FROM V$SQL

  7  WHERE SQL_TEXT LIKE 'SELECT * FROM TEST%';

 

SQL_ID         SQL_TEXT                         LITERAL_HASH_VALUE   HASH_VALUE BIND_DATA(NAME, POSITION, DUP_PO

-------------- -------------------------------- ------------------ ------------ --------------------------------

0r7m5jyz9ng09  SELECT * FROM TEST WHERE NAME=:N                  0   3197778953 SQL_BIND_SET(SQL_BIND(NULL, 1, N

               AME                                                              ULL, 1, 'NVARCHAR2(128)', 2000,

                                                                                NULL, NULL, 128, '04-SEP-17', 'K

                                                                                KKK', ANYDATA()))

 

 

SQL> COL SQL_ID FOR A14;

SQL> COL SQL_TEXT FOR A32;

SQL> COL HASH_VALUE FOR 99999999999;

SQL> COL BIND_DATA FOR A32;

SQL> SELECT SQL_ID          

  2        ,SQL_TEXT

  3        ,LITERAL_HASH_VALUE

  4        ,HASH_VALUE

  5        ,DBMS_SQLTUNE.EXTRACT_BIND(BIND_DATA,1).VALUE_STRING BIND_DATA

  6  FROM V$SQL

  7  WHERE SQL_TEXT LIKE 'SELECT * FROM TEST%';

 

SQL_ID         SQL_TEXT                         LITERAL_HASH_VALUE   HASH_VALUE BIND_DATA

-------------- -------------------------------- ------------------ ------------ --------------------------------

0r7m5jyz9ng09  SELECT * FROM TEST WHERE NAME=:N                  0   3197778953 KKKK

如果此时你给变量NAME赋值为kerry,然后你使用上面SQL语句查询,你会发现绑定变量的值依然为"KKKK",这个是因为绑定变量何时被捕获是有一定规律的:

1 含有绑定变量的sql语句被硬解析时

2 当含有绑定变量的sql语句以软解析或者软软解析方式重复执行时,该SQL语句中的绑定变量的具体输入值也可能被ORACLE捕获,只不过默认情况下这种捕获操作

受隐含参数_cursor_bind_capture_interval影响,默认需要间隔15(900秒)分钟才会做一次

SQL> exec :NAME :='kerry';

PL/SQL procedure successfully completed.

SQL> /

ID NAME

---------- --------------------------------

1000 kerry

SQL>

方法2:查询wrh$_sqlstat

V$SQL中有BIND_DATA字段,当SQL被解析时,就会放到BIND_DATA字段中,最终会被存入wrh$_sqlstat。关于wrh$_sqlstat的介绍如下所示:

wrh$_sqlstat contains a history for SQL execution statistics and stores snapshots of v$sql view.

wrh$_sqlstat中存储是v$sql的执行统计信息的快照的历史记录,那么从这里可以查询到一些历史绑定变量的值,但是也有可能v$sql的快照信息没有被捕获到(如满足什么条件才会被捕获呢?)。如下截图所示

SQL> select dbms_sqltune.extract_bind(bind_data, 1).value_string

  2  from wrh$_sqlstat

  3  where sql_id='0r7m5jyz9ng09';

 

no rows selected

如上测试所示,这个获取绑定变量值的方法有一定的缺陷性,有可能V$SQL快照信息没有被捕获到,导致wrh$_sqlstat

里面查不到对应的信息。

注意,如果有1个的绑定值,可以使用如下查询

select dbms_sqltune.extract_bind(bind_data, 1).value_string   

 

from wrh$_sqlstat

 

where sql_id = '1t2r2p48w4p0g'

如果有2个绑定值,可以使用如下查询

select dbms_sqltune.extract_bind(bind_data, 1).value_string||

'

'--'||dbms_sqltune.extract_bind(bind_data, 2).value_string

 

  from wrh$_sqlstat

 

 where sql_id = '1t2r2p48w4p0g'

如果有多个绑定变量,使用类似下面SQL

select dbms_sqltune.extract_bind(bind_data, 1).value_string

     ||'-'|| dbms_sqltune.extract_bind(bind_data, 2).value_string 

     ||'-'|| dbms_sqltune.extract_bind(bind_data, 3).value_string 

     ||'-'|| dbms_sqltune.extract_bind(bind_data, 4).value_string 

     ||'-'|| dbms_sqltune.extract_bind(bind_data, 5).value_string 

     ||'-'|| dbms_sqltune.extract_bind(bind_data, 6).value_string

from wrh$_sqlstat

where sql_id = '1t2r2p48w4p0g'

/

方法3:v$sql_bind_capture

使用 V$SQL_BIND_CAPTURE获取绑定变量的值,也有一些限制:

1、如果STATISTICS_LEVEL设置成BASIC,那绑定变量的捕捉就会关闭(Bind capture is disabled when the STATISTICS_LEVEL initialization parameter is set to BASIC.)

2、默认是900秒捕捉一次绑定变量值,由_cursor_bind_capture_interval参数控制。

3、V$SQL_BIND_CAPTURE视图中记录的绑定变量只对WHERE条件后面的绑定进行捕获,这点需要使用的时候注意。

对于DML操作,V$SQL_BIND_CAPTURE无法获取绑定变量的值。

SQL> COL NAME FOR A12;

SQL> COL DATATYPE_STRING FOR A24;

SQL> COL VALUE_STRING FOR A32;

SQL> SELECT NAME, 

  2         DATATYPE_STRING, 

  3         VALUE_STRING, 

  4         MAX_LENGTH, 

  5         LAST_CAPTURED 

  6  FROM   V$SQL_BIND_CAPTURE 

  7  WHERE  SQL_ID = '1t2r2p48W4P0g'; 

 

NAME         DATATYPE_STRING          VALUE_STRING                     MAX_LENGTH LAST_CAPT

------------ ------------------------ -------------------------------- ---------- ---------

:NAME        NVARCHAR2(128)           KD                                    128 04-SEP-17

 

SQL> 

v$sql_bind_capture视图,可以查看绑定变量,但是这个视图不太给力,只能捕获最后一次记录的绑定变量值。而且两次捕获的间隔也是受隐含参数_cursor_bind_capture_interval控制。默认是900秒后才会重新开始捕获。在900内,绑定变量值的改变不会反应在这个视图中。这个跟v$sql获取变量值是一样的。

SQL> EXEC :NAME :='kerry';

PL/SQL procedure successfully completed.

SQL>/

ID NAME

---------- --------------------------------

1000 kerry

SQL>

如上所示,我给变量赋予新的值,然后重新执行一次,你执行上面SQL,发现绑定变量的值为kerry了,之前的值KD就无法找到了。所以这个也是这个视图的一个局限性。(注意,实验结果结果也有可能是KD,这个取决于实验的时间间隔与隐含参数_cursor_bind_capture_interval的值有关系)

This view can be joined with V$SQLAREA on (HASH_VALUE, ADDRESS) and with V$SQL on (HASH_VALUE, CHILD_ADDRESS).

--

SET PAUSE ON

SET PAUSE 'Press Return to Continue'

SET PAGESIZE 60

SET LINESIZE 300

 

COLUMN sql_text FORMAT A120

COLUMN sql_id FORMAT A13

COLUMN bind_name FORMAT A10

COLUMN bind_value FORMAT A26

 

SELECT

  sql_id,

  t.sql_text sql_text,  

  b.name bind_name,

  b.value_string bind_value

FROM

  v$sql t

JOIN

  v$sql_bind_capture b  using (sql_id)

WHERE

  b.value_string is not null

AND

  sql_id='&sqlid'

/

 

 

SELECT

  b.sql_id,

  t.sql_text sql_text,  

  b.name bind_name,

  b.value_string bind_value

FROM

  v$sql t

JOIN

  v$sql_bind_capture b  on t.hash_value = b.hash_value and t.child_address = b.child_address

WHERE

  b.value_string is not null

AND

  b.sql_id='&sqlid'

/

方法4:查询视图DBA_HIST_SQLBIND.

DBA_HIST_SQLBIND是视图V$SQL_BIND_CAPTURE历史快照. 所以从视图DBA_HIST_SQLBIND能查到多个绑定变量的值。但是这里依然会遇到一个问题,就是有可能历史快照没有被捕获到DBA_HIST_SQLBIND下。如下测试所示:

SELECT SNAP_ID, 

       NAME, 

       POSITION, 

       VALUE_STRING, 

       LAST_CAPTURED, 

       WAS_CAPTURED 

FROM   DBA_HIST_SQLBIND 

WHERE  SQL_ID = '&SQL_ID' 

       AND SNAP_ID = &SNAP_ID; 

 

 

 

 

SELECT SNAP_ID, 

       NAME, 

       POSITION, 

       VALUE_STRING, 

       LAST_CAPTURED, 

       WAS_CAPTURED 

FROM   DBA_HIST_SQLBIND 

WHERE  SQL_ID = '&SQL_ID';

SQL> SELECT SNAP_ID, 

  2         NAME, 

  3         POSITION, 

  4         VALUE_STRING, 

  5         LAST_CAPTURED, 

  6         WAS_CAPTURED 

  7  FROM   DBA_HIST_SQLBIND 

  8  WHERE  SQL_ID = '&SQL_ID';

Enter value for sql_id: 1t2r2p48w4p0g

old   8: WHERE  SQL_ID = '&SQL_ID'

new   8: WHERE  SQL_ID = '1t2r2p48w4p0g'

 

no rows selected

 

SQL> exec dbms_workload_repository.create_snapshot();

 

PL/SQL procedure successfully completed.

 

SQL> SELECT SNAP_ID, 

  2         NAME, 

  3         POSITION, 

  4         VALUE_STRING, 

  5         LAST_CAPTURED, 

  6         WAS_CAPTURED 

FROM   DBA_HIST_SQLBIND 

  7    8  WHERE  SQL_ID = '&SQL_ID';

Enter value for sql_id: 1t2r2p48w4p0g

old   8: WHERE  SQL_ID = '&SQL_ID'

new   8: WHERE  SQL_ID = '1t2r2p48w4p0g'

 

no rows selected

 

SQL> 

方法5:dbms_xplan.display_cursor

sql_id:       指定位于库缓存执行计划中SQL语句的父游标。默认值为null。当使用默认值时当前会话的最后一条

SQL语句的执行计划将被返回。 可以通过查询V$SQL 或V$SQLAREA的SQL_ID列来获得SQL语句的SQL_ID。

child_number  指定父游标下子游标的序号。即指定被返回执行计划的SQL语句的子游标。默认值为0。如果为null,

则sql_id所指父游标下所有子游标的执行计划都将被返回。

format       控制SQL语句执行计划的输出部分,即哪些可以显示哪些不显示。

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

 

 

-------------------------------------

SELECT * FROM TEST WHERE NAME=:NAME

 

Plan hash value: 1357081020

 

--------------------------------------------------------------------------

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |

|*  1 |  TABLE ACCESS FULL| TEST |     1 |    31 |     3   (0)| 00:00:01 |

--------------------------------------------------------------------------

 

Query Block Name / Object Alias (identified by operation id):

-------------------------------------------------------------

 

   1 - SEL$1 / TEST@SEL$1

 

Outline Data

-------------

 

  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')

      DB_VERSION('11.2.0.1')

      ALL_ROWS

      OUTLINE_LEAF(@"SEL$1")

      FULL(@"SEL$1" "TEST"@"SEL$1")

      END_OUTLINE_DATA

  */

 

Peeked Binds (identified by position):

--------------------------------------

 

   1 - :NAME (VARCHAR2(30), CSID=873): 'KKK'

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   1 - filter("NAME"=:NAME)

 

Column Projection Information (identified by operation id):

-----------------------------------------------------------

 

   1 - "TEST"."ID"[NUMBER,22], "NAME"[VARCHAR2,32]

方法6:10046事件捕获绑定变量

alter session set events '10046 trace name context forever, level 4'; --level=4 表示启用SQL_TRACE并捕捉跟踪文件中的绑定变量。

实验在此略过,其实ORACLE中seq$表更新频繁的分析案例中已经展示如何使用10046事件捕获绑定变量的值。另外v$sql,v$sql_bind_capture、dba_hist_sqlbind只能捕获查询SQL(确切的说,只对WHERE条件后面的绑定变量进行捕获)的绑定变量,但10046也能捕获DML的SQL的值

最后如果需要可以通过alter system set "_cursor_bind_capture_interval"=10; 修改绑定变量捕获的时间间隔。

ORACLE获取SQL绑定变量值的方法总结的更多相关文章

  1. 获取oracle sql语句中绑定变量值的方法

    在诊断 sql的性能问题时,我们有时候须要获取其绑定变量的实际值,然后将此实际值带入到sql语句其中,用原来的sql构成select语句(带where条件),实际的运行一下,看一下选择性怎样. 本文就 ...

  2. php怎么获取js的变量值

    使用php做网站的时候,经常需要我们与前端的页面进行交互,有时候我们还需要通过php来获得js变量中的值,这种情况我们可以通过在其中嵌入js代码的方式来获得这个变量. 首先我们创建一个test的php ...

  3. Django 使用getattr() 方法获取配置文件的变量值

    在django项目的开发过程中,有时需要获取配置文件里的变量值,可以通过下面这样的方式去进行获取 from django.conf import settings item = getattr(set ...

  4. C++交换两个变量值的方法

    简单地列一下交换两个变量值地几种方法. 1.通过第三方实现,这一种也是最最最常见普通的方法: void swap(int *a, int *b) { int tmp = *a; *a = *b; *b ...

  5. sql server2008 获取动态sql的变量值

    --通过SQL 字符串 查询 获取查出的值sp_executesql declare @QuerySql nvarchar(500),@uid int,@Ucode varchar(100);set ...

  6. 不同页面获取同一cookie变量值不同的问题及解决方法

    在使用cookie时发现不同页面获取到的同一个cookie变量的值不同,本篇博客介绍其中一种情况的解决方法,通过设置path的方法可使得在同一个网站下获取的cookie变量一致. 问题描述 在www. ...

  7. Oracle、SQL Server、MySQL分页方法

    测试用例:查询TEST_TABLE表中TEST_COLUMN列的第10-20条数据 1,Oracle分页方法 SELECT A.* FROM ( SELECT ROWNUM ROWNO, B.* FR ...

  8. 如何获取SQL Server数据库元数据的方法

    发布时间:2007.06.15 05:05    来源:赛迪网    作者:3946469 元数据简介 元数据 (metadata) 最常见的定义为“有关数据的结构数据”,或者再简单一点就是“关于数据 ...

  9. springmvc请求参数获取(自动绑定)的几种方法

    1.直接把表单的参数写在Controller相应的方法的形参中,适用于get方式提交,不适用于post方式提交. /** * 1.直接把表单的参数写在Controller相应的方法的形参中 * @pa ...

随机推荐

  1. spring-boot-maven-plugin插件的作用

    要记住:spring-boot-maven-plugin插件在打Jar包时会引入依赖包 可以打成直接运行的Jar包 maven项目的pom.xml中,添加了org.springframework.bo ...

  2. 【EF6学习笔记】(十一)实施继承

    上篇链接:EF学习笔记(十) 处理并发 本篇原文链接:Implementing Inheritance 面向对象的世界里,继承可以很好的重用代码.在本章就对Instructor和Student两个类进 ...

  3. tcp关闭状态详解

    tcp关闭连接不区分客户端和服务端,哪一端口可以主动发起关闭连接请求.所以为了描述方便,描述中的“主动方”表示主动发起关闭连接一方,“被动方”表示被动关闭连接一方. 1. tcp关闭连接状态转换 上图 ...

  4. 2.Magicodes.NET框架之路——策略管理

    闲话策略 策略,有很多解释.但鄙人个人比较看重这点: 策略,是为了实现某个目标或者针对某些问题而制定的应对方案,以最终实现目标.比如为实现生娃而XXOO. 因此在本框架中,策略(Strategy),则 ...

  5. input的三个属性autocomplete、autocapitalize和autocorrect

    下面的input的三个属性是H5新增的属性 <input type="text" class="input-search" placeholder=&qu ...

  6. Java之判断大整数是否为平方数

      在本篇博客中,我们将讨论如何使用有效的算法来判断一个大整数是否为平方数.   给定正整数\(n\),如果存在一个整数\(m\),满足\(m^{2}=n\),那么则称\(n\)为平方数.因此,判断一 ...

  7. [转]GitLab Continuous Integration (GitLab CI/CD)

    本文转自:https://docs.gitlab.com/ee/ci/README.html GitLab Continuous Integration (GitLab CI/CD) The bene ...

  8. 第一册:lesson thirty seven。

    原文: Making a bookcase. A:You are working hard,George. What are you doing . B:I am making a bookcase. ...

  9. Java集合类源码解析:AbstractMap

    目录 引言 源码解析 抽象函数entrySet() 两个集合视图 操作方法 两个子类 参考: 引言 今天学习一个Java集合的一个抽象类 AbstractMap ,AbstractMap 是Map接口 ...

  10. 【Spring】31、Spring的EL表达式

    一.简介 Spring3中引入了Spring表达式语言—SpringEL,SpEL是一种强大,简洁的装配Bean的方式,他可以通过运行期间执行的表达式将值装配到我们的属性或构造函数当中,更可以调用JD ...