2011-11-24RESULT_CACHE函数-创新互联

/tupian/20230522/thread-1499223-19-1.html

成都创新互联公司专注于汕头企业网站建设,成都响应式网站建设公司,商城网站定制开发。汕头网站建设公司,为汕头等地区提供建站服务。全流程按需定制,专业设计,全程项目跟踪,成都创新互联公司专业和态度为您提供的服务

185楼

我创建了如下的表并填入数据:

CREATE TABLE plch_tab
(
   this_is_it       VARCHAR2 (20)
, another_column   NUMBER (2)
)
/
BEGIN
   INSERT INTO plch_tab (this_is_it)
        VALUES ('PL/SQL Challenge');
   COMMIT;
END;
/

然后我编译了如下的函数:

CREATE OR REPLACE FUNCTION plch_foo (p_in_value IN NUMBER)
   RETURN VARCHAR2
   RESULT_CACHE
IS
   lvretval   plch_tab.this_is_it%TYPE;
BEGIN
   SELECT this_is_it INTO lvretval FROM plch_tab;
   DBMS_OUTPUT.put_line (lvretval);
   RETURN lvretval;
END;
/

哪些代码块执行之后会显示 "PL/SQL Challenge" 仅仅一次?

(A)

DECLARE
   lvdummy   plch_tab.this_is_it%TYPE;
BEGIN
   lvdummy := plch_foo (NULL);
   lvdummy := plch_foo (NULL);
END;
/
SQL> DECLARE
  2     lvdummy   plch_tab.this_is_it%TYPE;
  3  BEGIN
  4     lvdummy := plch_foo (NULL);
  5     lvdummy := plch_foo (NULL);
  6  END;
  7  /
PL/SQL Challenge
PL/SQL procedure successfully completed
SQL>

(B)

DECLARE
  lvDummy  plch_tab.this_is_it%TYPE;
BEGIN
  lvDummy := plch_foo(1);
  lvDummy := plch_foo(1);
END;
/
SQL> DECLARE
  2    lvDummy  plch_tab.this_is_it%TYPE;
  3  BEGIN
  4    lvDummy := plch_foo(1);
  5    lvDummy := plch_foo(1);
  6  END;
  7  /
PL/SQL Challenge
PL/SQL procedure successfully completed
SQL>

(C)

DECLARE
   lvdummy   plch_tab.this_is_it%TYPE;
BEGIN
   lvdummy := plch_foo (2);
   UPDATE plch_tab SET another_column = 1;
   COMMIT;
   lvdummy := plch_foo (2);
END;
/
SQL> DECLARE
  2     lvdummy   plch_tab.this_is_it%TYPE;
  3  BEGIN
  4     lvdummy := plch_foo (2);
  5  
  6     UPDATE plch_tab SET another_column = 1;
  7     COMMIT;
  8  
  9     lvdummy := plch_foo (2);
 10  END;
 11  /
PL/SQL Challenge
PL/SQL Challenge
PL/SQL procedure successfully completed
SQL>

(D)

DECLARE
   lvdummy   plch_tab.this_is_it%TYPE;
BEGIN
   lvdummy := plch_foo (3);
   UPDATE plch_tab SET another_column = 1;
   lvdummy := plch_foo (3);
END;
/
SQL> DECLARE
  2     lvdummy   plch_tab.this_is_it%TYPE;
  3  BEGIN
  4     lvdummy := plch_foo (3);
  5  
  6     UPDATE plch_tab SET another_column = 1;
  7  
  8     lvdummy := plch_foo (3);
  9  END;
 10  /
PL/SQL Challenge
PL/SQL Challenge
PL/SQL procedure successfully completed
SQL>

(E)

DECLARE
   lvdummy   plch_tab.this_is_it%TYPE;
BEGIN
   lvdummy := plch_foo (4);
   UPDATE plch_tab
      SET another_column = 1
    WHERE another_column = 2;
   lvdummy := plch_foo (4);
END;
/
SQL> DECLARE
  2     lvdummy   plch_tab.this_is_it%TYPE;
  3  BEGIN
  4     lvdummy := plch_foo (4);
  5  
  6     UPDATE plch_tab
  7        SET another_column = 1
  8      WHERE another_column = 2;
  9  
 10     lvdummy := plch_foo (4);
 11  END;
 12  /
PL/SQL Challenge
PL/SQL procedure successfully completed
SQL>

答案说明在191楼

2011-11-24 答案ABE.
PL/SQL 函数的结果缓存机制提供了一种把PL/SQL 函数的结果缓存在SGA里面的办法,这个结果对运行应用程序的所有会话都是可用的。缓存机制简单而且有效,你不必再费心设计开发自己的缓存及其管理机制。
为了打开函数的结果缓存,你只需在函数头加上RESULT_CACHE子句(如果在PACKAGE里面使用,则包头和包体中的函数声明都必须有这个子句)
当一个结果缓存函数被调用时,系统检查缓存。如果以前调用的结果存在于缓存中,参数也相同,系统直接返回结果二不是再次执行函数体。如果缓存中找不到该结果,系统执行函数体,并在把控制权交还给调用者之前,把结果加入到缓存(针对于这组参数)。
函数结果缓存通常保存在函数体中查询到的一个或多个表的数据。ORACLE需要确保这个数据的拷贝是干净的(即未被修改过)。
ORACLE通过两个机制来确保数据干净:
1. 每当表发生了修改并被提交,所有依赖于这个表的结果缓存将被清空。随后对函数的调用会导致数据再次进入缓存。
2. 一旦你在会话中修改了表,那么所有依赖于这个表的缓存将被忽略。即:缓存结果依赖于被改过的表的函数体将会被执行,一直到你提交或回滚了这些修改。
A: 两次调用参数都为NULL, ORACLE认为没有变化,直接取缓存结果而不是重新调用。
B: 同上,参数没有发生变化。
C: 参数没有发生变化,但是代码修改了 plch_foo 表,函数的缓存对当前会话不再有效;COMMIT发生后,CACHE对所有会话都不再有效。因此再次调用函数时,函数被再次执行了
D: 同上,虽然没有COMMIT, 但是该缓存对当前会话已经不可用了,所以函数会被再次执行。
   假如这个选项后面还有更多的调用:lvdummy := plch_foo (3);
   则函数体每次都会被重新执行。
E: UPDATE没有修改任何数据,因此缓存仍然有效。

新闻名称:2011-11-24RESULT_CACHE函数-创新互联
网站路径:http://scyanting.com/article/dhijes.html