PL/SQL Challenge 每日一题:2014-3-14 11gR2中带RELIES_ON子句的RESULT_CACHE函数

最先答对且答案未经编辑的puber将获得纪念章一枚(答案不可编辑但可发新贴补充或纠正),其他会员如果提供有价值的分析、讨论也可获得纪念章一枚。

以往旧题索引:
http://www.itpub.net/forum.php?mod=forumdisplay&fid=3&filter=typeid&typeid=1808

原始出处:
http://www.plsqlchallenge.com/

作者:        mentzel.iudith

运行环境:SQLPLUS, SERVEROUTPUT已打开
注:本题给出答案时候要求给予简要说明才能得到奖品
执行环境: 11gR2

我创建了如下的表和数据:

CREATE TABLE plch_employees
(
   employee_id  INTEGER
, last_name    VARCHAR2(100)
, salary       NUMBER
)
/

BEGIN
   INSERT INTO plch_employees
      VALUES (100, 'Steven', 10000);

COMMIT;
END;
/

哪些选项实现了一个名为plch_salary的函数,使得下列代码块执行之后:

BEGIN
    DBMS_OUTPUT.put_line( plch_salary(100) );
    DBMS_OUTPUT.put_line( plch_salary(100) );

UPDATE plch_employees
    SET   salary = salary * 2
    WHERE employee_id = 100 ;

COMMIT;

DBMS_OUTPUT.put_line( plch_salary(100) );
END;
/

我们可以看到结果中有三个完全一致的数值?

(A)
CREATE OR REPLACE FUNCTION plch_salary
           (p_employee_id_in IN plch_employees.employee_id%TYPE)
       RETURN plch_employees.salary%TYPE
       RESULT_CACHE
       RELIES_ON (plch_employees)
AS
    l_salary   plch_employees.salary%TYPE;
BEGIN
    SELECT salary
    INTO l_salary
    FROM plch_employees
    WHERE employee_id = p_employee_id_in ;

RETURN l_salary ;
END;
/

(B)
CREATE OR REPLACE FUNCTION plch_salary
           (p_employee_id_in IN plch_employees.employee_id%TYPE)
       RETURN plch_employees.salary%TYPE
       RESULT_CACHE
       RELIES_ON (plch_employees)
AS
    l_salary   plch_employees.salary%TYPE;
BEGIN
    UPDATE plch_employees
    SET   salary = salary * 2
    WHERE employee_id = p_employee_id_in
    RETURNING salary INTO l_salary ;

COMMIT;

RETURN l_salary ;
END;
/

(C)
CREATE OR REPLACE FUNCTION plch_salary
            (p_employee_id_in IN plch_employees.employee_id%TYPE)
       RETURN plch_employees.salary%TYPE
       RESULT_CACHE
       RELIES_ON (plch_employees)
AS
    l_salary   plch_employees.salary%TYPE;
BEGIN
    UPDATE plch_employees
    SET   salary = salary * 2
    WHERE employee_id = p_employee_id_in ;

COMMIT;

SELECT salary
    INTO l_salary
    FROM plch_employees
    WHERE employee_id = p_employee_id_in ;

RETURN l_salary ;
END;
/

(D)
CREATE OR REPLACE FUNCTION plch_salary
            (p_employee_id_in IN plch_employees.employee_id%TYPE)
       RETURN plch_employees.salary%TYPE
       RESULT_CACHE
       RELIES_ON (plch_employees)
AS
    l_salary   plch_employees.salary%TYPE;
BEGIN
  EXECUTE IMMEDIATE
     'SELECT salary FROM plch_employees
        WHERE employee_id = :employee_id'
      INTO l_salary
      USING p_employee_id_in ;

RETURN l_salary ;
END;
/

(E)
CREATE OR REPLACE FUNCTION plch_salary
           (p_employee_id_in IN plch_employees.employee_id%TYPE)
       RETURN plch_employees.salary%TYPE
       RESULT_CACHE
       RELIES_ON (plch_employees)
AS
    l_salary   plch_employees.salary%TYPE;
BEGIN
    DELETE FROM plch_employees
      WHERE employee_id = p_employee_id_in
      RETURNING salary INTO l_salary ;

COMMIT;

RETURN l_salary ;
END;
/

(F)
CREATE OR REPLACE FUNCTION plch_salary
           (p_employee_id_in IN plch_employees.employee_id%TYPE)
       RETURN plch_employees.salary%TYPE
       RESULT_CACHE
       RELIES_ON (plch_employees)
AS
    l_salary   plch_employees.salary%TYPE;
BEGIN
    INSERT INTO plch_employees
       VALUES ( 500 + p_employee_id_in,
                'New Employee',
                (SELECT 2*salary FROM plch_employees
                    WHERE employee_id = p_employee_id_in)
              )
       RETURNING salary INTO l_salary ;
      
    COMMIT;

RETURN l_salary ;
END;
/

liwei9902
发表于 2014-3-18 10:13:42

a 猜的

renfengjun
发表于 2014-3-18 10:23:42

正确答案:B、E、F
A 错误,update之后,result cache改变了。
B 结果正确,但是有点无法理解。
C 错误,第二次执行plch_salary(100) 的时候,其实使用的是result cache,没有真正执行update,在匿名块的update以后,result cache就改变了。所以其实一共执行了三次update。
D 错误,前两次的结果肯定是一样的,执行update之后,result cache改变了。
E 正确,结果正确,和B一样,无法理解。
F 正确,结果正确,和BE一样,无法理解。或者说只要加returning 子句的dml语句,都可以认定为不会影响result cache?并且也不受其他语句的影响?

liwei9902
发表于 2014-3-18 14:03:26

看了解答,发现result cache不是很实用,至少在我需要的功能中,不很实用

newkid
发表于 2014-3-19 03:23:49

答案BEF, 3楼得奖。

A: 函数结果被缓存,所以前两个调用都返回10000。但是,在UPDATE被执行后,函数再次被执行,这次返回20000。
B: 在Oracle 11gR2, RELIES_ON子句被忽略,数据库自动跟踪缓存结果所依赖的对象。令人惊奇的是,如果函数只在一张表上执行了一个UPDATE,并利用RETURNING子句返回一个列值,这张表并不会被注册为缓存结果所依赖的对象。

这个直接后果导致所有的UPDATE语句(函数内有一个,匿名块中有一个)都不会影响缓存结果,所以三次输出都是同样的值20000。
必须注意这个现象与11gR1不同,在该版本中RELIES_ON决定了缓存结果的依赖关系。

C:  一旦函数中包含了一个SELECT语句,缓存结果就会标记为依赖于PLCH_EMPLOYEES,所以前两个函数调用都返回20000, 但是在匿名块中的UPDATE语句执行之后,函数再次被执行,这次它返回80000。

在Oracle 11gR1中,这个选项的结果会有所不同,对于本题目同样是不正确的:

20000
40000
160000

D:
结果缓存依赖关系是由Oracle在执行的时候建立的,不是在编译的时候建立的。因此,虽然这个函数包含了一个动态的SELECT语句,结果缓存仍然会依
赖于PLCH_EMPLOYEES表,结果和静态的SELECT一样。前两个函数调用返回10000,
但是在UPDATE执行之后,第三个结果是20000。

E: 如果函数只在一张表上执行了一个DELETE,并利用RETURNING子句返回一个列值,这张表并不会被注册为缓存结果所依赖的对象。结果,不论是DELETE语句或者是匿名块中的UPDATE语句都不会使得缓存结果失效。
结果,我们会看到10000被显示三次。

必须注意这个现象与11gR1不同,在该版本中RELIES_ON决定了缓存结果的依赖关系。在该版本中,我们会看到10000仅仅被显示一次,随后是两个空值,因为在记录删除之后,缓存结果失效,函数再次执行并且返回了空值。

F: 此处函数确实执行了plch_employees表上的SELECT语句,但是仅仅用于INSERT语句中的VALUES子句的标量子查询。
在这种情况下,这张表并不会被注册为缓存结果所依赖的对象,因此,不论是INSERT语句或者是匿名块中的UPDATE语句都不会使得缓存结果失效。
结果,函数只会被执行一次,缓存结果20000会被显示三次。
必须注意这个现象与11gR1不同,在该版本中RELIES_ON决定了缓存结果的依赖关系。在该版本中,每次函数执行都会使得缓存结果失效,原因是
INSERT语句,所以,前两次执行会返回同样的值20000,而第三次执行发生于UPDATE语句之后,会返回40000。

dcswinner
发表于 2014-3-20 23:08:31

newkid 老师真牛逼,学习了。

newkid
发表于 2014-3-21 02:29:35

dcswinner 发表于 2014-3-20 23:08 static/image/common/back.gif
newkid 老师真牛逼,学习了。

NB个P, 这道题考的是11gR2的一个疑似bug的怪异表现,所以我做错了。

Bleach_ud
发表于 2014-3-22 10:27:52

newkid 发表于 2014-3-19 03:23 static/image/common/back.gif
答案BEF, 3楼得奖。

A: 函数结果被缓存,所以前两个调用都返回10000。但是,在UPDATE被执行后,函数再次 ...

漲姿勢了~~~

页:
[1]

PL/SQL Challenge 每日一题:2014-3-14 11gR2中带RELIES_ON子句的RESULT_CACHE函数的更多相关文章

  1. 【python】Leetcode每日一题-寻找旋转排序数组中的最小元素

    [python]Leetcode每日一题-寻找旋转排序数组中的最小元素 [题目描述] 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组nums ...

  2. [LeetCode每日一题]80. 删除有序数组中的重复项 II

    [LeetCode每日一题]80. 删除有序数组中的重复项 II 问题 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度. 不要使用额外 ...

  3. 【python】Leetcode每日一题-寻找旋转排序数组中的最小元素2

    [python]Leetcode每日一题-寻找旋转排序数组中的最小元素2 [题目描述] 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组nums ...

  4. [每日一题2020.06.14]leetcode #70 爬楼梯 斐波那契数列 记忆化搜索 递推通项公式

    题目链接 题意 : 求斐波那契数列第n项 很简单一道题, 写它是因为想水一篇博客 勾起了我的回忆 首先, 求斐波那契数列, 一定 不 要 用 递归 ! 依稀记得当年校赛, 我在第一题交了20发超时, ...

  5. [ X.XX]CF每日一题系列线下更新中

    现在做的都好水啊,就不写博客了,线下有记录滴

  6. Oracle数据库—— PL/SQL基础编程

    一.涉及内容 1. 掌握PL/SQL程序块的结构,理解并熟悉各种变量的应用. 二.具体操作 (一)使用system用户登录SQL*PLUS,使用SQL语句创建用户:u_你的姓名首字母(例如:u_zs) ...

  7. PL/SQL学习笔记(三)

    -----创建一个序列,再创建一个表(主键是数字),通过序列生成该表的主键值. create table mytb1( m_id number primary key, m_name ) not nu ...

  8. PL/SQL精明的调用栈分析

    PL/SQL精明的调用栈分析 原文:http://www.oracle.com/technetwork/issue-archive/2014/14-jan/o14plsql-2045346.html ...

  9. Oracle PL/SQL随堂笔记总结

    1.pl/sql编程 2.存储过程 3.函数 4.触发器 5.包 6.pl/sql基础 -定义并使用变量 7.pl/sql的进阶 8.oracle的视图 1.pl/sql编程 1.理解oracle的p ...

随机推荐

  1. Linux进程状态解析

    引言 Linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有不同的状态.  在下文将对进程的R.S.D.T.Z.X 六种状态做个说明. PROCE ...

  2. jsp简单学习总结

    以下均为jsp页面 1:<jsp:include page="index.jsp"/>相当于嵌入一个页面.还有一种是<frame src="main_l ...

  3. Tornado集成Apscheduler定时任务

    熟悉Python的人可能都知道,Apscheduler是python里面一款非常优秀的任务调度框架,这个框架是从鼎鼎大名的Quartz移植而来. 之前有用过Flask版本的Apscheduler做定时 ...

  4. QT 制作串口调试小助手----(小白篇)

    一.成品图展示 简介:因zigbee实验,制作一个相对简易版的上位机,接收来自zigbee无线传感采集的温湿度.光照等数据. 并且将数据部分描绘成实时动态折线统计图. 二.主要功能介绍 主要使用QT自 ...

  5. Java学习-异常2

    1.异常处理的第一种方式是:上抛[throws] 2.异常处理的第二种方式是:try....catch..如果不想让调用程序知道该异常发生了,被调用的程序应该使用try...catch..进行异常捕捉 ...

  6. j建立一个小的servlet小程序

    我们建立一个最简单的servlet程序,这个servelt程序只是单纯的输出helloworld. 步骤如下:如图:在Eclipse中选择新建一个项目,其中选择tomcat project然后点击下一 ...

  7. B-Tree 漫谈 (从二叉树到二叉搜索树到平衡树到红黑树到B树到B+树到B*树)

    关于B树的学习还是需要做点笔记. B树是为磁盘或者其他直接存取辅助存储设备而设计的一种平衡查找树.B树与红黑树的不同在于,B树可以有很多子女,从几个到几千个.比如一个分支因子为1001,高度为2的B树 ...

  8. 8.Layers Editor

    图层编辑 Ventuz5中有两种类型的场景,分别是2D图层和3D图层.3D图层包含Content和Hierarchy,而2D图层只包含Content.默认情况下,图层编辑器显示在Ventuz中的左上角 ...

  9. Android 获取android安装apk框的安装状态(如点击取消、返回)

    最近鼓捣android,碰到个问题,因为没有root权限,需要调用Intent安装apk,但需要获取用户是否安装了(如,用户点击了返回或取消),查了很多文章,最后可以解决,但有瑕疵,解决方法如下: p ...

  10. android Activity实现底部滑动弹出窗口及源码下载地址

    在做微信.微博.qq等分享时,一般是点击分享按钮后会从底部弹出滑动窗口,然后选择要分享的社交平台进行分享.今日头条.腾讯新闻等内容App的评论也是从底部滑动弹出输入窗口,进行评论输入的.本篇文章就讲讲 ...