【发布时间】:2014-05-21 00:43:34
【问题描述】:
这是有问题的示例 SQL; SQL 应该在任何 Oracle DBMS 上运行(我运行的是 11.2.0.2.0)。
请注意结果集中的 UUID 值是如何不同的(一个有 898,另一个有 899),尽管是从内联视图/with 子句中构建的。在下面您可以看到 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
稳定 SYS_GUID 的 SQL Fiddle: http://sqlfiddle.com/#!4/d41d8/29409
SQL Fiddle 这显示了奇怪的 SYS_GUID 行为: http://sqlfiddle.com/#!4/d41d8/29411
【问题讨论】:
-
一直在玩这个 - 有趣的是,只有当您选择 DBMS_OUTPUT.RANDOM 的值两次或更多次时,该值才会稳定 - 请参阅sqlfiddle.com/#!4/d41d8/29447,我只使用该值一次并注意到 UUID 不再一样的……
-
您可能想查看stackoverflow.com/questions/6776366/… 的前两个答案。 Oracle 在调用函数的方式上往往有点难以预测(部分原因在于它优化查询的方式),因此这个问题可能没有可靠的答案。
-
可以看到不同的执行计划:SQl-Fiddle。 SQL-Server 的
NEWID()具有类似的、不可预测的行为,具体取决于所选的执行计划。 -
继续我的游戏 - 似乎“DBMS_RANDOM”作为一个名称在给出 SYS_GUID() 的“修复”行为方面有点神奇。我刚刚通过将系统 DBMS_RANDOM 包替换为包含返回数字“4”的单个函数的包来破坏本地安装,并且修复行为仍然存在 - 但调用同一个包“DBMS_RANDOM2”并且修复行为消失了......
-
this 是您指的 AskTom 帖子吗? (“我已经写了数千次了,你无法依赖 SQL 会调用你的函数的次数、时间或时间。”)