http://www.itpub.net/thread-1499223-19-1.html

185楼

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

CREATETABLEplch_tab(this_is_itVARCHAR2(20),another_columnNUMBER(2))/BEGININSERTINTOplch_tab(this_is_it)VALUES('PL/SQLChallenge');COMMIT;END;/

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

CREATEORREPLACEFUNCTIONplch_foo(p_in_valueINNUMBER)RETURNVARCHAR2RESULT_CACHEISlvretvalplch_tab.this_is_it%TYPE;BEGINSELECTthis_is_itINTOlvretvalFROMplch_tab;DBMS_OUTPUT.put_line(lvretval);RETURNlvretval;END;/

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

(A)

DECLARElvdummyplch_tab.this_is_it%TYPE;BEGINlvdummy:=plch_foo(NULL);lvdummy:=plch_foo(NULL);END;/

SQL>DECLARE2lvdummyplch_tab.this_is_it%TYPE;3BEGIN4lvdummy:=plch_foo(NULL);5lvdummy:=plch_foo(NULL);6END;7/PL/SQLChallengePL/SQLproceduresuccessfullycompletedSQL>

(B)

DECLARElvDummyplch_tab.this_is_it%TYPE;BEGINlvDummy:=plch_foo(1);lvDummy:=plch_foo(1);END;/

SQL>DECLARE2lvDummyplch_tab.this_is_it%TYPE;3BEGIN4lvDummy:=plch_foo(1);5lvDummy:=plch_foo(1);6END;7/PL/SQLChallengePL/SQLproceduresuccessfullycompletedSQL>

(C)

DECLARElvdummyplch_tab.this_is_it%TYPE;BEGINlvdummy:=plch_foo(2);UPDATEplch_tabSETanother_column=1;COMMIT;lvdummy:=plch_foo(2);END;/

SQL>DECLARE2lvdummyplch_tab.this_is_it%TYPE;3BEGIN4lvdummy:=plch_foo(2);56UPDATEplch_tabSETanother_column=1;7COMMIT;89lvdummy:=plch_foo(2);10END;11/PL/SQLChallengePL/SQLChallengePL/SQLproceduresuccessfullycompletedSQL>

(D)

DECLARElvdummyplch_tab.this_is_it%TYPE;BEGINlvdummy:=plch_foo(3);UPDATEplch_tabSETanother_column=1;lvdummy:=plch_foo(3);END;/

SQL>DECLARE2lvdummyplch_tab.this_is_it%TYPE;3BEGIN4lvdummy:=plch_foo(3);56UPDATEplch_tabSETanother_column=1;78lvdummy:=plch_foo(3);9END;10/PL/SQLChallengePL/SQLChallengePL/SQLproceduresuccessfullycompletedSQL>

(E)

DECLARElvdummyplch_tab.this_is_it%TYPE;BEGINlvdummy:=plch_foo(4);UPDATEplch_tabSETanother_column=1WHEREanother_column=2;lvdummy:=plch_foo(4);END;/

SQL>DECLARE2lvdummyplch_tab.this_is_it%TYPE;3BEGIN4lvdummy:=plch_foo(4);56UPDATEplch_tab7SETanother_column=18WHEREanother_column=2;910lvdummy:=plch_foo(4);11END;12/PL/SQLChallengePL/SQLproceduresuccessfullycompletedSQL>

答案说明在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没有修改任何数据,因此缓存仍然有效。