楼主: Kenniu

[原创] 也谈Oracle 数据库的绑定变量特性及应用

[复制链接]
论坛徽章:
4
开发板块每日发贴之星
日期:2007-07-23 01:03:36CTO参与奖
日期:2009-02-20 09:44:202010新春纪念徽章
日期:2010-03-01 11:20:052013年新春福章
日期:2013-02-25 14:51:24
21#
发表于 2009-7-14 16:46 | 只看该作者

回复 #13 Kenniu 的帖子

首先感谢楼主的分享~
我有个问题,类似12楼的情况,在存储过程中,要查询的语句是动态的。我尝试使用绑定变量,但绑定变量只是相当于把值赋值给变量,而不会去执行“查询”,我把SQL贴出来:
insert_str := '
      INSERT INTO bam_cbbs_base_kpi_sum_l2_l(busi_id
                                           , user_type
                                           , chrg_prov_id
                                           , oper_time
                                           , base_kpi_id
                                           , value
                                           , dimension_level
                                           , is_valid
                                           , created
                                           , modified
                                           )
    ';
select_str := '
        SELECT :busi_id
             , user_type
             , rov_name
             , SUBSTR(curr_deal, 1, 6)
             , :kpi_id
             , :sum_str
             , 5
             , 1
             , sysdate
             , sysdate
          FROM :tab
           AND SUBSTR(curr_deal, 1, 6) = to_char(:time)
         GROUP BY substr(curr_deal,1,6),user_type,rov_name
      ';
execute immediate insert_str || select_str using busi_id,prov_id,kpi_id(i),sum_str,curr_deal;
这个语句执行后,会把对应的表达式赋值给绑定变量,但却没任何记录返回,因为他只简单的赋值了,却没执行select操作。但是如果这个绑定变量的内容是数据库某条记录的一个值,却可以。如select * from tab1 where a = :a;这个a是个值,如'123','abc'什么的,都可以。
我为了解决上述的问题,我想了一个笨办法。
我先通过tmp_str := 'select rov_name from dual';
execute immediate tmp_str into new_prov_str using prov_name(i);
的办法获得这个new_str,然后上面的查询语句改成了绑定变量+拼接字符串的形式。如:
select_str := '
        SELECT :busi_id
             , user_type
             , '||new_prov_str||'
             , SUBSTR(curr_deal, 1, 6)
             , :kpi_id
             , '||new_sum_str||'
             , 5
             , 1
             , sysdate
             , sysdate
             '||new_where_str||'
           AND SUBSTR(curr_deal, 1, 6) = to_char(:time)
         GROUP BY substr(curr_deal,1,6),user_type,'||new_prov_str||'
      ';
但是这个办法其实是“错误的”,并没有用到绑定变量的特性。而是有点蒙混过关的感觉,呵呵。

不知道大家有没明白我说的?
扼要的说:绑定变量,如果其内容是个表达式的话,应该如何使用绑定变量?

使用道具 举报

回复
论坛徽章:
4
开发板块每日发贴之星
日期:2007-07-23 01:03:36CTO参与奖
日期:2009-02-20 09:44:202010新春纪念徽章
日期:2010-03-01 11:20:052013年新春福章
日期:2013-02-25 14:51:24
22#
发表于 2009-7-14 16:54 | 只看该作者

回复 #21 封烨 的帖子

晕,上图的 的内容是 : prov_name

使用道具 举报

回复
论坛徽章:
1
2009日食纪念
日期:2009-07-22 09:30:00
23#
发表于 2009-7-22 22:51 | 只看该作者
请问在c和C++程序中怎么使用oracle的绑定变量啊

使用道具 举报

回复
论坛徽章:
46
托尼托尼·乔巴
日期:2017-01-03 11:47:42喜羊羊
日期:2015-03-10 14:01:432015年新春福章
日期:2015-03-06 11:57:31沸羊羊
日期:2015-03-04 14:43:43马上有房
日期:2014-12-29 13:45:35马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11夏利
日期:2014-01-28 09:42:56雪铁龙
日期:2013-10-09 13:33:15秀才
日期:2016-01-21 13:37:04
24#
 楼主| 发表于 2009-8-7 10:29 | 只看该作者
原帖由 封烨 于 2009-7-14 16:46 发表
首先感谢楼主的分享~
我有个问题,类似12楼的情况,在存储过程中,要查询的语句是动态的。我尝试使用绑定变量,但绑定变量只是相当于把值赋值给变量,而不会去执行“查询”,我把SQL贴出来:
insert_str := '
      INSERT INTO bam_cbbs_base_kpi_sum_l2_l(busi_id
                                           , user_type
                                           , chrg_prov_id
                                           , oper_time
                                           , base_kpi_id
                                           , value
                                           , dimension_level
                                           , is_valid
                                           , created
                                           , modified
                                           )
    ';
select_str := '
        SELECT :busi_id
             , user_type
             , rov_name
             , SUBSTR(curr_deal, 1, 6)
             , :kpi_id
             , :sum_str
             , 5
             , 1
             , sysdate
             , sysdate
          FROM :tab
           AND SUBSTR(curr_deal, 1, 6) = to_char(:time)
         GROUP BY substr(curr_deal,1,6),user_type,rov_name
      ';
execute immediate insert_str || select_str using busi_id,prov_id,kpi_id(i),sum_str,curr_deal;
这个语句执行后,会把对应的表达式赋值给绑定变量,但却没任何记录返回,因为他只简单的赋值了,却没执行select操作。但是如果这个绑定变量的内容是数据库某条记录的一个值,却可以。如select * from tab1 where a = :a;这个a是个值,如'123','abc'什么的,都可以。
我为了解决上述的问题,我想了一个笨办法。
我先通过tmp_str := 'select rov_name from dual';
execute immediate tmp_str into new_prov_str using prov_name(i);
的办法获得这个new_str,然后上面的查询语句改成了绑定变量+拼接字符串的形式。如:
select_str := '
        SELECT :busi_id
             , user_type
             , '||new_prov_str||'
             , SUBSTR(curr_deal, 1, 6)
             , :kpi_id
             , '||new_sum_str||'
             , 5
             , 1
             , sysdate
             , sysdate
             '||new_where_str||'
           AND SUBSTR(curr_deal, 1, 6) = to_char(:time)
         GROUP BY substr(curr_deal,1,6),user_type,'||new_prov_str||'
      ';
但是这个办法其实是“错误的”,并没有用到绑定变量的特性。而是有点蒙混过关的感觉,呵呵。

不知道大家有没明白我说的?
扼要的说:绑定变量,如果其内容是个表达式的话,应该如何使用绑定变量?


其实,我不建议你这么做;
原因是你用在Store-Procedure中;只要写在Store-procedure,Oracle 系统现在都自动帮你把你写的Sql,转义成你要用的绑定变量;尤其Oralce9i以后的版本;当然Oracle 8I以前的版本是无法做到的;

我强烈建议你用静态绑定;你的动态绑定会花费更多的资源,且效率有可能并是你想的那么好;

另外,你想知道是否Oracle在使用绑定变量,其实我在文章已经说的很清楚了;

使用道具 举报

回复
论坛徽章:
46
托尼托尼·乔巴
日期:2017-01-03 11:47:42喜羊羊
日期:2015-03-10 14:01:432015年新春福章
日期:2015-03-06 11:57:31沸羊羊
日期:2015-03-04 14:43:43马上有房
日期:2014-12-29 13:45:35马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11夏利
日期:2014-01-28 09:42:56雪铁龙
日期:2013-10-09 13:33:15秀才
日期:2016-01-21 13:37:04
25#
 楼主| 发表于 2009-8-7 10:30 | 只看该作者
原帖由 lakepanda 于 2009-7-22 22:51 发表
请问在c和C++程序中怎么使用oracle的绑定变量啊


这个看起来,我要Study一下...呵呵...

使用道具 举报

回复
论坛徽章:
46
托尼托尼·乔巴
日期:2017-01-03 11:47:42喜羊羊
日期:2015-03-10 14:01:432015年新春福章
日期:2015-03-06 11:57:31沸羊羊
日期:2015-03-04 14:43:43马上有房
日期:2014-12-29 13:45:35马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11夏利
日期:2014-01-28 09:42:56雪铁龙
日期:2013-10-09 13:33:15秀才
日期:2016-01-21 13:37:04
26#
 楼主| 发表于 2009-8-7 10:32 | 只看该作者
这里也有一篇,“何时Oracle使用绑定变量性能反而更差”的文章,供大家参考;内容请参考别人写的东西...

http://www.mscto.com/Oracle/2009010137072.html

使用道具 举报

回复
论坛徽章:
46
托尼托尼·乔巴
日期:2017-01-03 11:47:42喜羊羊
日期:2015-03-10 14:01:432015年新春福章
日期:2015-03-06 11:57:31沸羊羊
日期:2015-03-04 14:43:43马上有房
日期:2014-12-29 13:45:35马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11夏利
日期:2014-01-28 09:42:56雪铁龙
日期:2013-10-09 13:33:15秀才
日期:2016-01-21 13:37:04
27#
 楼主| 发表于 2009-8-7 10:44 | 只看该作者
原帖由 lakepanda 于 2009-7-22 22:51 发表
请问在c和C++程序中怎么使用oracle的绑定变量啊


这里找到了C程序中的使用oracle的绑定变量的方法:

这篇文章的实在基于Linux写的C程序编写,引用了基于Linux下的一个函数库,Kai Poitschke开发的Libsqlora8;
或许你也可以用Oracle数据库对C语言的接口就是OCI(Oracle Common Interface) C-Library;
但具体思想应该没什么错误;

下面是来自于另一位网友(http://www.cndw.com/tech/server/2006040533965.asp)的代码内容,思路大同:


char *update_stmt =
"UPDATE ocitest.upload_log SET upload_fresh = '0' where log_name = :1";
if (0 <= (sth = sqlo_prepare(dbh, update_stmt)))
{ if (SQLO_SUCCESS !=
(sqlo_bind_by_name(sth, ":1", SQLOT_STR, packet_name, 64, NULL, 0)
))
{ printf("sqlo_bind_param failed failed: %s\n", sqlo_geterror(dbh) );
return 0;
}
}
if (SQLO_SUCCESS != sqlo_execute(sth, 1))
{ printf("sqlo_execute failed: %s\n", sqlo_geterror(dbh) );
return 0;
}
上面的代码显示了如何通过名字绑定变量,“:1”在Oracle SQL语句中表示为一个变量(名字随意),在sqlo_bind_by_name函数中与packet_name变量绑定。在变量绑定完毕后,就可以调用sqlo_execute函数来执行这个SQL语句。

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
28#
发表于 2009-11-12 10:36 | 只看该作者
记录学习

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
29#
发表于 2009-11-23 18:03 | 只看该作者
原帖由 Case2000 于 2006-9-24 13:17 发表
有一个现实的问题是,基本上据我接触过的程序员来看,没有人喜欢用绑定变量。

绑定变量的确能够大幅度提高性能,尤其在OLTP场合。
更进一步,如果有可能,就不要关闭游标,利用游标不断进行操作,比软解析效率还要高很多。
但对程序员是比较复杂的,我们的办法,写一些通用函数帮助程序员做这事,成功的解决了问题,程序员在使用这些函数的时候都不知不觉的使用了绑定变量和保留游标。

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
30#
发表于 2009-11-23 18:07 | 只看该作者
原帖由 lakepanda 于 2009-7-22 22:51 发表
请问在c和C++程序中怎么使用oracle的绑定变量啊

在OCI环境下很容易的:
该帖的后部分,接受了建议,采用了绑定变量,而且实现了保留游标,确实大幅度提高了性能。
http://www.itpub.net/viewthread. ... p;extra=&page=1

数据包装器提供一组函数,帮助程序员使用数据库最优秀的特性。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表