这是有问题的示例SQL; SQL应该在任何Oracle DBMS上运行(我运行的是11.2.0.2.0).
注意尽管是在内联视图/ with子句中构建的,但结果集中的UUID值是如何不同的(一个具有898,另一个具有899).在下面你可以看到DBMS_RANDOM.RANDOM()没有这种副作用.
SQL:
WITH data AS (SELECT SYS_GUID () uuid FROM DUAL)
SELECT uuid, uuid
FROM data
Run Code Online (Sandbox Code Playgroud)
输出:
UUID UUID_1
F8FCA4B4D8982B55E0440000BEA88F11 F8FCA4B4D8992B55E0440000BEA88F11
Run Code Online (Sandbox Code Playgroud)
在Contrast DBMS_RANDOM中 ,结果是相同的
SQL:
WITH data AS (SELECT DBMS_RANDOM.RANDOM() rand FROM DUAL)
SELECT rand, rand
FROM data
Run Code Online (Sandbox Code Playgroud)
输出:
RAND RAND_1
92518726 92518726
Run Code Online (Sandbox Code Playgroud)
更有趣的是我可以通过包含对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
Run Code Online (Sandbox Code Playgroud)
稳定SYS_GUID的SQL小提琴:http://sqlfiddle.com/#!4/d41d8/29409
SQL Fiddle显示奇怪的SYS_GUID行为:http://sqlfiddle.com/#!4/d41d8/29411
该文件给出了一个理由,为什么你会看到一个差异(重点煤矿):
警告:
因为SQL是一种声明性语言,而不是命令式(或程序性)语言,所以你不知道SQL语句调用的函数将运行多少次 - 即使该函数是用PL/SQL(一种命令式语言)编写的.如果您的应用程序要求函数执行一定次数,请不要从SQL语句调用该函数.请改用光标.
例如,如果应用程序要求为每个选定的行调用函数,则打开游标,从游标中选择行,然后为每一行调用函数.此技术保证对函数的调用次数是从游标获取的行数.
基本上,Oracle没有指定在sql语句中调用函数的次数:它可能取决于发布,环境,访问路径以及其他因素.
但是,有一些方法可以限制查询重写,如嵌套子查询的Unnesting一章所述:
子查询不需要的东西,并将子查询的主体合并到包含它的语句的主体中,允许优化器在评估访问路径和连接时将它们一起考虑.除了一些例外,优化器可以取消大多数子查询.这些异常包括分层子查询和包含ROWNUM伪列的子查询,集合运算符之一,嵌套聚合函数或对查询块的相关引用,该查询块不是子查询的直接外部查询块.
如上所述,您可以使用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
Run Code Online (Sandbox Code Playgroud)