我从一些表中提取随机样本并注意到,根据我编写查询的方式,它不起作用。显然,我没有使用all_tab_columns,我只提供了一个可以在vanilla实例(9.2.0.8)上运行的示例。
为什么这样做?
select * from (
select
floor(dbms_random.value(0,1000)) as randomval
from
all_tab_columns where rownum < 10000
) where randomval > 200 and randomval < 300;
但这不会返回任何结果。
select * from (
select
floor(dbms_random.value(0,1000)) as randomval
from
all_tab_columns
) where randomval > 200 and randomval < 300;
rownum&lt;查询中的10000完成了吗?
编辑:澄清什么不起作用。
编辑:添加版本9.2.0.8
答案 0 :(得分:2)
我没有明确的答案,但我有一个理论......
我的猜测是你的第二个查询正在优化:
select *
from all_tab_columns
where floor(dbms_random.value(0,1000))> 200
and floor(dbms_random.value(0,1000)) < 300;
并且在内联视图中以某种方式具有rownum
条件会阻止优化。
这也可以解释为什么我们中的一些人(包括我)无法看到您描述的问题 - 因为我们使用的是不同版本的Oracle,并且查询会针对我们进行不同的优化。
修改强>
经过一段谷歌搜索,我遇到了this AskTom question,这似乎是相关的。 Tom Kyte的回答以这一行结束:
从SQL调用函数时,最好不要依赖于频率 函数被调用,以什么顺序或其他什么。简而言之,假设 没有。并记住 - SQL重写启动,我们重写您的SQL 一直以来。不要依赖副作用
答案 1 :(得分:1)
我认为@Peter正在做些什么,但需要更多解释。
在Oracle中,函数可以是DETERMINISTIC。这意味着当使用相同的参数调用时,该函数返回相同的值。所以,sqrt()
是确定性的; dbms_random()
不是。其他数据库使用术语STABLE与VOLATILE这两个类别。
如果我不得不猜测,Oracle引擎足够聪明,知道以下查询应返回行:
select * from (
select
dbms_random.value(0,1000) as randomval
from
all_tab_columns
) where randomval > 200 and randomval < 300;
然而,由于floor()
,我怀疑它会被绊倒。也就是说,编译器检测到“稳定”函数,因此它只查找前一个值。并且,它使用缓存值,多次调用函数进行短路。
如果这是正确的,那么上面的查询将返回行。如果是这样,那么我会把数据库的这个“特性”称为一个错误 - 可能有一个数据库优化工程师,但是,谁会将其作为一个非常有用的功能进行辩护。
答案 2 :(得分:0)
您的两个查询都在Oracle 11g R2中运行。 ROWNUM是Oracle中的伪列,如果感兴趣,可以阅读它。