Oracle SQL:在内联视图中存在时,了解SYS_GUID()的行为?

这里是sql的例子。 sql应该在任何Oracle DBMS上运行(我正在运行11.2.0.2.0)。

注意,尽管在内联视图/ with子句中构建了UUID值,但是结果集中的UUID值是不同的(一个有898对象有899个)。下面你可以看到DBMS_RANDOM.RANDOM()没有这个副作用。

sql

WITH data AS (SELECT SYS_GUID () uuid FROM DUAL)
    SELECT uuid,uuid
      FROM data

输出

UUID                                      UUID_1
F8FCA4B4D8982B55E0440000BEA88F11      F8FCA4B4D8992B55E0440000BEA88F11

在对比度DBMS_RANDOM中,结果是一样的

sql

WITH data AS (SELECT DBMS_RANDOM.RANDOM() rand FROM DUAL)
SELECT rand,rand
  FROM data

输出

RAND    RAND_1
92518726    92518726

更有趣的是,我可以通过将调用包括到DBMS_RANDOM.RANDOM来改变行为/稳定sys_guid:

WITH data AS (
        SELECT SYS_GUID () uuid,DBMS_RANDOM.random () rand 
        FROM DUAL)
SELECT uuid a,uuid b,rand c,rand d
  FROM data

稳定的sql小提琴SYS_GUID:
http://sqlfiddle.com/#!4/d41d8/29409

sql Fiddle显示奇怪的SYS_GUID行为:
http://sqlfiddle.com/#!4/d41d8/29411

documentation gives a reason为什么你可能会看到一个差异(强调我的):

Caution:

Because sql is a declarative language,rather than an imperative (or procedural) one,you cannot know how many times a function invoked by a sql statement will run—even if the function is written in PL/sql,an imperative language.
If your application requires that a function be executed a certain number of times,do not invoke that function from a sql statement. Use a cursor instead.

For example,if your application requires that a function be called for each selected row,then open a cursor,select rows from the cursor,and call the function for each row. This technique guarantees that the number of calls to the function is the number of rows fetched from the cursor.

基本上,Oracle没有指定在sql语句中调用一个函数次数:它可能取决于发行版本,环境,访问路径等因素。

但是,有一些方法来限制查询重写,如第Unnesting of Nested Subqueries章所述:

Subquery unnesting unnests and merges the body of the subquery into the body of the statement that contains it,allowing the optimizer to consider them together when evaluating access paths and joins. The optimizer can unnest most subqueries,with some exceptions. Those exceptions include hierarchical subqueries and subqueries that contain a ROWNUM pseudocolumn,one of the set operators,a nested aggregate function,or a correlated reference to a query block that is not the immediate outer query block of the subquery.

如上所述,您可以使用ROWNUM伪列来防止Oracle不察觉子查询

sql> WITH data AS (SELECT SYS_GUID() uuid FROM DUAL WHERE ROWNUM >= 1)
  2  SELECT uuid,uuid FROM data;

UUID                             UUID
-------------------------------- --------------------------------
1ADF387E847F472494A869B033C2661A 1ADF387E847F472494A869B033C2661A

相关文章

数据库版本:11.2.0.4 RAC(1)问题现象从EM里面可以看到,在23号早上8:45~8:55时,数据库等待会话暴增...
(一)问题背景最近在对一个大约200万行数据的表查看执行计划时,发现存在异常,理论上应该返回100多万...
(一)删除备份--DELETE命令用于删除RMAN备份记录及相应的物理文件。当使用RMAN执行备份操作时,会在RM...
(1)DRA介绍 数据恢复顾问(Data Recovery Advise)是一个诊断和修复数据库的工具,DRA能够修复数据文...
RMAN(Recovery Manager)是Oracle恢复管理器的简称,是集数据库备份(backup)、修复(restore)和恢复...
(1)备份对象 可以使用RMAN进行的备份对象如下: --整个数据库:备份所有的数据文件和控制文件; --数...