Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2828080
  • 博文数量: 599
  • 博客积分: 16398
  • 博客等级: 上将
  • 技术积分: 6875
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-30 12:04
个人简介

WINDOWS下的程序员出身,偶尔也写一些linux平台下小程序, 后转行数据库行业,专注于ORACLE和DB2的运维和优化。 同时也是ios移动开发者。欢迎志同道合的朋友一起研究技术。 数据库技术交流群:58308065,23618606

文章分类

全部博文(599)

文章存档

2014年(12)

2013年(56)

2012年(199)

2011年(105)

2010年(128)

2009年(99)

分类: Oracle

2012-02-21 12:57:03

 

PL/SQL、Pro*C中避免是用绑定变量的方法(一)http://blog.chinaunix.net/uid-22948773-id-3078314.html

 

上面主要介绍了绑定变量的对SQL执行计划的影响,以及在PL/SQL中如何避免。

下面简单介绍一下如何在Pro*C中避免。

当然如果SQL是拼凑起来的动态SQL,譬如:

sprintf(sqltext,"select object_name from test where object_type='%s' and object_id=%d","SYNONYM",1234);

这种情况下是肯定可以的,因为每一个SQL语句都会硬解析一次,每一个SQL语句都有自己的执行计划。

为了将硬解析减少到最少,我们尽量在object_id列上也用绑定变量,而在object_type上采用非绑定变量。


下面是测试数据:


SQL> select object_id,object_name,object_type from test where object_id in (605,8473);


 OBJECT_ID OBJECT_NAME          OBJECT_TYP
---------- -------------------- ----------

       605 MAP_OBJECT           SYNONYM
      8473 FGR$AUTOPURGE_JOB    JOB

下面介绍2种方法来实现绑定变量和非绑定变量的同时使用

方法1-采用动态SQL方法3


刷新共享池,清除以前SQL语句的执行计划。

SQL> alter system flush shared_pool;


System altered.


SQL>  select sql_text,executions,sql_id from v$sql where sql_text like 'select object_name from test where object_type%';


no rows selected

 


Pro*C代码如下:

#include
#include
exec sql include sqlca;

main()
{
 
  exec sql begin declare section;
     char *username="test";
     char *password="test";
     char *dbserver="10.223.18.116/yansp";
     char sqltext[128];
     char v_object_type[30];
     int  v_object_id;
     varchar v_object_name[30];
  exec sql end declare section;
 
  exec sql declare s statement;
  exec sql declare c cursor for s;

  exec sql connect :username identified by :password using :dbserver;
 

  strcpy(v_object_type,"SYNONYM");
  v_object_id=605;
   
  sprintf(sqltext,"select object_name from test where object_type='%s' and object_id=:object_id",v_object_type);
  exec sql prepare s from :sqltext;
  exec sql open c using :v_object_id;
  exec sql fetch c into v_object_name;
  v_object_name.arr[v_object_name.len]='\0';
  printf("object_name=[%s]\n",v_object_name.arr);
  exec sql close c;
 
  strcpy(v_object_type,"JOB");
  v_object_id=8473;
   
  sprintf(sqltext,"select object_name from test where object_type='%s' and object_id=:object_id",v_object_type);
  exec sql prepare s from :sqltext;
  exec sql open c using :v_object_id;
  exec sql fetch c into v_object_name;
  v_object_name.arr[v_object_name.len]='\0';
  printf("object_name=[%s]\n",v_object_name.arr);
  exec sql close c;
 
  exec sql commit work release;
}

 

编译成可执行程序test 执行结果如下:

/home/cpicsrv/yansp > ./test
object_name=[MAP_OBJECT]
object_name=[FGR$AUTOPURGE_JOB]
/home/cpicsrv/yansp >


共享池中的SQL执行情况如下:

SQL> select sql_text,executions,sql_id from v$sql where sql_text like 'select object_name from test where object_type%';


SQL_TEXT                                 EXECUTIONS SQL_ID
---------------------------------------- ---------- -------------

select object_name from test where objec          1 4z597uqf88aqt
t_type='JOB' and object_id=:object_id

select object_name from test where objec          1 93n27g7ykmvmg
t_type='SYNONYM' and object_id=:object_i
d

 

 

再次执行./test

/home/cpicsrv/yansp > ./test
object_name=[MAP_OBJECT]
object_name=[FGR$AUTOPURGE_JOB]
/home/cpicsrv/yansp >


SQL> select sql_text,executions,sql_id from v$sql where sql_text like 'select object_name from test where object_type%';


SQL_TEXT                                 EXECUTIONS SQL_ID
---------------------------------------- ---------- -------------

select object_name from test where objec          2 4z597uqf88aqt
t_type='JOB' and object_id=:object_id

select object_name from test where objec          2 93n27g7ykmvmg
t_type='SYNONYM' and object_id=:object_i
d

每条SQL的执行次数都变为了2。

 

 

方法2-嵌入式PL/SQL


#include
#include
exec sql include sqlca;

main()
{
 
  exec sql begin declare section;
     char *username="test";
     char *password="test";
     char *dbserver="10.223.18.116/yansp";
     char sqltext[128];
     char v_object_type[30];
     int  v_object_id;
     varchar v_object_name[30];
  exec sql end declare section;

  exec sql connect :username identified by :password using :dbserver;
 
  v_object_name.len=sizeof(v_object_name.arr);

  strcpy(v_object_type,"SYNONYM");
  v_object_id=605;
  sprintf(sqltext,"select object_name from test where object_type='%s' and object_id=:object_id",v_object_type);
 
  exec sql execute
    begin
      execute immediate :sqltext into :v_object_name using :object_id;
    end;
  end-exec;
  v_object_name.arr[v_object_name.len]='\0';
  printf("object_name=[%s]\n",v_object_name.arr); 
 
  strcpy(v_object_type,"JOB");
  v_object_id=8473;
  sprintf(sqltext,"select object_name from test where object_type='%s' and object_id=:object_id",v_object_type);
 
  exec sql execute
    begin
      execute immediate :sqltext into :v_object_name using :object_id;
    end;
  end-exec;
  v_object_name.arr[v_object_name.len]='\0';
  printf("object_name=[%s]\n",v_object_name.arr);
 
  exec sql commit work release;
}

 

将上述代码编译成可执行程序test。


再次清空共享池

SQL> alter system flush shared_pool;


System altered.


SQL> select sql_text,executions,sql_id from v$sql where sql_text like 'select object_name from test where object_type%';


no rows selected

 


/home/cpicsrv/yansp > ./test
object_name=[MAP_OBJECT]
object_name=[FGR$AUTOPURGE_JOB]
/home/cpicsrv/yansp >

再次查看共享池的结果如下:

SQL> select sql_text,executions,sql_id from v$sql where sql_text like 'select object_name from test where object_type%';


SQL_TEXT                                 EXECUTIONS SQL_ID
---------------------------------------- ---------- -------------

select object_name from test where objec          1 4z597uqf88aqt
t_type='JOB' and object_id=:object_id

select object_name from test where objec          1 93n27g7ykmvmg
t_type='SYNONYM' and object_id=:object_i
d

 

 

阅读(2106) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~