本文总结一下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_DATAFROM V$SQLWHERE 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_DATAFROM V$SQLWHERE 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_stringfrom wrh$_sqlstatwhere 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_stringfrom wrh$_sqlstatwhere 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 ONSET PAUSE 'Press Return to Continue'SET PAGESIZE 60SET LINESIZE 300

COLUMN sql_text FORMAT A120COLUMN sql_id FORMAT A13COLUMN bind_name FORMAT A10COLUMN bind_value FORMAT A26

SELECT  sql_id,  t.sql_text sql_text,    b.name bind_name,  b.value_string bind_valueFROM  v$sql tJOIN  v$sql_bind_capture b  using (sql_id)WHERE  b.value_string is not nullAND  sql_id='&sqlid'/

SELECT  b.sql_id,  t.sql_text sql_text,    b.name bind_name,  b.value_string bind_valueFROM  v$sql tJOIN  v$sql_bind_capture b  on t.hash_value = b.hash_value and t.child_address = b.child_addressWHERE  b.value_string is not nullAND  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: 1t2r2p48w4p0gold   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: 1t2r2p48w4p0gold   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赋值_ORACLE获取SQL绑定变量值的方法总结相关推荐

  1. oracle 带有变量的语句_Oracle 动态SQL语句(2)之含变量的WHERE语句与日期变量

    在 Oracle 动态SQL语句(1)中提到基本动态SQL语句书写,但在写动态SQL语句时特别要注意日期型变量和WHERE语句的编写. 如下代码: 1.注意在执行动态SQL语句时,execute im ...

  2. mysql 存储过程如何声明多个变量赋值_mysql存储过程:定义变量,赋值,判断,输出...

    1.定义变量,赋值,判断,输出 DROP PROCEDURE IF EXISTS proc_first; -- 如果proc_first存在就删除 create procedure proc_firs ...

  3. tp5获取sql_tp5 sql语句 tp5 获取sql语句

    tp5 sql语句 tp5 获取sql语句以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! sql语句转换成tp5执行,求 ...

  4. oracle plsql 绑定变量值,dbms_sqltune解析SQL的BIND_DATA绑定变量值

    dbms_sqltune解析SQL的BIND_DATA绑定变量值 SQL> select dbms_sqltune.extract_bind(bind_data, 1).value_string ...

  5. php使用使用外部变量的值,PHP实现函数内修改外部变量值的方法示例

    PHP实现函数内修改外部变量值的方法示例 本文实例讲述了PHP实现函数内修改外部变量值的方法.分享给大家供大家参考,具体如下: 直接上代码,如下: $a_str = 'ab'; function ch ...

  6. php如何获取html的值,请教同一个文件中php如何获取html的变量值?

    代码如下: 配置器 请设置您要修改的属性:金币: 经验: 道具:test connect."; echo ($jb);echo ($jb);echo ($jy);?> 在浏览器打开这个 ...

  7. 用html5交换两个变量的值,JavaScript交换两个变量值的七种解决方案

    前言 这篇文章总结了七种办法来交换a和b的变量值 var a = 123; var b = 456; 交换变量值方案一 最最最简单的办法就是使用一个临时变量了,不过使用临时变量的方法实在是太low了 ...

  8. php 方法里用外部变量的值,PHP实现函数内修改外部变量值的方法示例

    本文实例讲述了PHP实现函数内修改外部变量值的方法.分享给大家供大家参考,具体如下: 直接上代码,如下: $a_str = 'ab'; function change_val(){ global $a ...

  9. oracle 定义变量及使用方法,Oracle pl/sql变量定义和使用详解

    一.变量介绍 在编写pl/sql程序时,可以定义变量和常量:在pl/sql程序中包括有: 1).标量类型(scalar) 2).复合类型(composite) --用于操作单条记录 3).参照类型(r ...

最新文章

  1. R语言dplyr包对数据进行超前或者之后处理(lead、lag)实战
  2. mysql中的merge into,SQL Server 2008中利用merge into关键实现insert/update自动匹配(类似于MySQL中的For Update关键字)...
  3. 【手把手教学】基于Maven构建方式使用Mybatis generator自动生成
  4. leetcode186. 翻转字符串里的单词 II
  5. 网页编程技术三(H5中表格的用法)
  6. [数据分析工具] Pandas 不可不知的功能(一)
  7. 使用Nginx制作下载站点
  8. i2c通信的详细讲解_STM32Cube15 | 使用硬件I2C读写温湿度传感器(SHT30)
  9. Linux下创建虚拟软盘镜像
  10. 阿里云ACE认证学习知识点梳理
  11. 集美大学校园网绑定/认证报错异常及解决方案
  12. 手把手教你PXE高效网络装机、Kickstart无人值守安装(详细版)
  13. python学习之——综合小游戏
  14. Python 用26个英文字母生成序列
  15. 网易云项目(Vue)
  16. c语言两个for语句并列执行_C语言for循环(for语句)详解
  17. 平面漩涡Shader
  18. ubuntu linux 下使用google eather
  19. velo2cam_calibration——最新最准确的激光雷达Lidar和相机Camera外参标定算法实现
  20. 界面控件BCGControlBar for .NET v7.1正式发布——支持VS 2022

热门文章

  1. 在php中调用java接口吗,php 调用 java 接口
  2. 编写一个C程序,实现以下功能:输入n个人的身高,然后从n个人中选出身高差值最小的两个人作为礼仪(如果差值相同的话,选取其中最高的两个人),要求输出两个礼仪的身高。
  3. 解析html生成xpath,html使用xpath解析xml
  4. c语言cis,c语言小白学习历程第五篇
  5. c++如何显示图片_Vue+laravel后端添加商品后图片如何显示?
  6. c语言几种排序方法的比较,基于C语言的几种排序方法比较.doc
  7. 档案盒正面标签制作_错题本科学制作方法、正确使用方式及窍门
  8. java中br.readline_java中br.readLine与 br.read的用法有什么区别??
  9. hdc mfc 画扇形图_MFC画图总结-DIB图形绘制
  10. oracle fs1 2多少u,甲骨文FS1系列闪存的“大道至简”