ITPUB??ì3
12月微软Hyper-V虚拟化沙龙主题征集
ITPUB论坛 » Oracle开发 » 很少受关注的SQL中一些函数调用秘密

标题: [精华] 很少受关注的SQL中一些函数调用秘密
  本主题由 System 于 2008-9-11 05:00 解除限时置顶 
离线 grubbyoo
▃▃,~


来自 夕阳小画
精华贴数 1
个人空间 6
技术积分 1682 (1035)
社区积分 349 (1789)
注册日期 2007-3-1
论坛徽章:15
2008北京奥运纪念徽章:皮划艇静水生肖徽章2007版:鸡2008北京奥运纪念徽章:射箭2008北京奥运纪念徽章:自行车2008北京奥运纪念徽章:手球2008北京奥运纪念徽章:射箭
      

发表于 2008-9-8 16:33 
期待很久,强贴留名,占位学习


__________________
走到哪里才不是过客
只看该作者    顶部
离线 jack198409
中级会员


来自 湖北武汉
精华贴数 0
个人空间 484
技术积分 3219 (476)
社区积分 3470 (416)
注册日期 2007-8-10
论坛徽章:35
NBA2008季后赛纪念徽章NBA季后赛之星2008北京奥运纪念徽章:沙滩排球2008北京奥运纪念徽章:沙滩排球2008北京奥运纪念徽章:射箭2008北京奥运纪念徽章:柔道
2008北京奥运纪念徽章:帆船2008北京奥运纪念徽章:排球2008北京奥运纪念徽章:垒球2008北京奥运纪念徽章:摔跤2008北京奥运纪念徽章:举重2008北京奥运纪念徽章:足球

发表于 2008-9-8 16:38 
研究,研究


__________________
金麟岂是池中物,一遇风云便化龙!


我的SPACE空间欢迎您!
   


只看该作者    顶部
离线 zhangfengh
老狐狸


精华贴数 3
个人空间 0
技术积分 14590 (79)
社区积分 7160 (220)
注册日期 2002-10-12
论坛徽章:123
现任管理团队成员生肖徽章2007版:鸡生肖徽章2007版:鸡生肖徽章2007版:鸡生肖徽章2007版:鸡生肖徽章2007版:鸡
生肖徽章:鸡生肖徽章:鸡生肖徽章:鸡生肖徽章:鸡生肖徽章:鸡生肖徽章:鸡

发表于 2008-9-8 16:40 
呵呵,这么快就放开了


__________________
=======================================
狐狸在这个世界上是凭借聪明而得到生存的,并且在这个世界上占有一席之地,学习狐狸的聪明,少走弯路。
=======================================
吸收别人的经验,使之成为自己的经验!
=======================================
只看该作者    顶部
离线 jolly10
一起看日落


来自 苏州
精华贴数 1
个人空间 226
技术积分 3909 (373)
社区积分 1216 (887)
注册日期 2005-3-7
论坛徽章:31
奥运纪念徽章生肖徽章2007版:羊体育版块博采纪念徽章   
      

发表于 2008-9-8 16:49 
进来学习!


__________________
MY ITPUB博客

If at first you don't succeed, try, try, try again.(再接再厲,終會成功.)
只看该作者    顶部
离线 anglei



精华贴数 1
个人空间 3
技术积分 787 (2455)
社区积分 2 (32850)
注册日期 2008-7-19
论坛徽章:3
2008北京奥运纪念徽章:足球2008北京奥运纪念徽章:跳水2008北京奥运纪念徽章:跳水   
      

发表于 2008-9-8 17:16 
看的不是很明白,晚上回去再看


只看该作者    顶部
离线 jiqing1004
吉庆


精华贴数 0
个人空间 0
技术积分 286 (6968)
社区积分 124 (3134)
注册日期 2007-5-26
论坛徽章:14
2008北京奥运纪念徽章:射击2008北京奥运纪念徽章:羽毛球2008北京奥运纪念徽章:摔跤2008北京奥运纪念徽章:羽毛球2008北京奥运纪念徽章:跆拳道2008北京奥运纪念徽章:足球
2008北京奥运纪念徽章:举重2008北京奥运纪念徽章:垒球2008北京奥运纪念徽章:击剑生肖徽章2007版:牛2008年新春纪念徽章 

发表于 2008-9-8 17:57 
先留个名  明天上班了慢慢看


__________________
感谢 voca 的足球~~~
只看该作者    顶部
离线 dingjun123
djゆoracle


来自 china
精华贴数 3
个人空间 0
技术积分 1919 (912)
社区积分 15 (8980)
注册日期 2006-7-28
论坛徽章:2
2008北京奥运纪念徽章:铁人三项ITPUB新首页上线纪念徽章    
      

发表于 2008-9-8 18:09 
的确不容易,终于进来踩一下了!


__________________
软件体系架构要以数据库为中心,如oracle,可以充分利用数据库的特性,帮助解决复杂的问题。一个常用的规则是:
如果能用单条sql解决,ok
如果不能用单条sql解决,考虑使用PL/SQL
如果不能用PL/SQL解决,考虑使用java存储过程
如果不能用java解决,那么考虑使用c外部过程
如果c都解决不了,那么考虑一下放弃吧
只看该作者    顶部
在线/呼叫 newkid
资深新手
老程序员


来自 银河系
精华贴数 2
个人空间 0
技术积分 2778 (579)
社区积分 0 (121048)
注册日期 2004-6-26
论坛徽章:5
生肖徽章2007版:马生肖徽章2007版:鸡2008北京奥运纪念徽章:垒球2008北京奥运纪念徽章:羽毛球  
      

发表于 2008-9-8 22:51 
呵呵,内部装修结束了?支持一下楼主的钻研精神。

关于#7, 可以用这个技巧:

SQL> exec pkg.reset_n;

PL/SQL procedure successfully completed.

SQL> select  * from (select pkg.inc_n n from t WHERE ROWNUM>0) where n = 2;

         N
----------
         2

照理说 NO_MERGE HINT 也可以,但我没试出来,不知道是什么道理。

参数不变时返回值也不变的函数叫 DETERMINISTIC 函数,在声明时可以加这个关键字,ORACLE会CACHE返回值。

另一个让ORACLE CACHE 住函数的方法是用SCALAR SUBQUERY:

SELECT ID, (SELECT DBMS_RANDOM.VALUE FROM DUAL) FROM T;

你会发现随机函数只发生了一次。

如果CBO认为每次子查询不一样,它还是会执行多次:

SELECT ID, (SELECT DBMS_RANDOM.VALUE FROM DUAL WHERE ID>0) FROM T;

函数调用次数是很难预测的,影响因素很多。到11G,函数的CACHE策略又发生了变化,不过我没有环境没法测。

等会有空我也贴几个有趣的例子上来。


__________________
只看该作者    顶部
离线 jvkojvko
小马哥


精华贴数 1
个人空间 0
技术积分 6044 (226)
社区积分 61171 (7)
注册日期 2007-9-10
论坛徽章:45
地主之星地主长老紫蜘蛛月度论坛发贴之星ITPUB评论家ITPUB评论家
BLOG每周发帖之星每日论坛发贴之星在线时间在线时间  

发表于 2008-9-8 23:12 
mark


__________________
马无夜草不肥,人无外财不富。
-------------------------------
小店:http://shop34160316.taobao.com/
欢迎光临,店家是俺GF
只看该作者    顶部
在线/呼叫 newkid
资深新手
老程序员


来自 银河系
精华贴数 2
个人空间 0
技术积分 2778 (579)
社区积分 0 (121048)
注册日期 2004-6-26
论坛徽章:5
生肖徽章2007版:马生肖徽章2007版:鸡2008北京奥运纪念徽章:垒球2008北京奥运纪念徽章:羽毛球  
      

发表于 2008-9-9 00:05 


QUOTE:
原帖由 nyfor 于 2008-9-8 16:23 发表
以上出现在 order by, group by 表达式中的函数调用与出现在 where 中的还有一个不同就是后者的函数调用表达式不论是否与表数据有关, 均对每一行数据都调用一次(注意这是筛选之后的每一行)

在WHERE中的函数调用是会受索引影响的。
我先稍微改造一下你的PACKAGE, 增加一个inc2_n:

create or replace package pkg
is
  function get_n return number;
  function inc_n return number;
  procedure reset_n;

  function inc2_n(p_n in number) return number;

end;
/

create or replace package body pkg
is
  g_n number;
  function get_n return number
  is
  begin
    return g_n;
  end;
  
  function inc_n return number
  is
  begin
    g_n := g_n + 1;
    return g_n;
  end;
  
  procedure reset_n
  is
  begin
    g_n := 0;
  end;

  function inc2_n(p_n in number) return number
  is
  begin
    g_n := g_n + 1;
    return p_n;
  end;

begin
  g_n := 0;
end;
/


开始试验:
exec pkg.reset_n;

select * from t where id=pkg.inc2_n(2);

select pkg.get_n from dual;

     GET_N
----------
         3          ----- 全表扫描,执行了三次
         

--- 增加一个索引再做同样试验
create index t_x on t(id);

exec pkg.reset_n;

select * from t where id=pkg.inc2_n(2);

select pkg.get_n from dual;

     GET_N
----------
         2       ----- 走了索引,执行了两次,不知道为什么不是一次


__________________
只看该作者    顶部
相关内容


CopyRight 1999-2006 itpub.net All Right Reserved.
北京皓辰广域网络信息技术有限公司. 版权所有
E-mail:Webmaster@itpub.net
京ICP证:010037号 联系我们 法律顾问