有趣的sql(2)

原文见http://www.itpub.net/showthread.php?s=&threadid=654

 

oldwain

 欣赏一个奇妙的sql(也来点正经的, 不能让他们说我们只会瞎灌水).
以下语句用来随机查找三条记录
select * from emp
where empno in ( select empno
from (select empno
from emp
order by dbms_random.random )
where rownum <= 3 )
/

不要怀疑这个语句有什么错误, 在oracle815以上肯定没有问题.

问题是:
1. dbms_random.random 产生的是一个8位或10位(随版本不同而不同),
order by 一个如此大的数字什么含义?

2. order by 不允许使用比实际列数更大的列(通过执行select * from emp order by 20的错误信息可以知道)

那么, 这个语句究竟为什么能够执行, 怎么执行的?


 qiaoyu

 我的oracle8.1.6上就不能执行!

 

 oldwain

 不能执行? 是不是没有安装dbms_random package? 安装后应该没有问题的.

执行ORACLE_HOME/RDBMS/ADMIN/CATOCTK.SQL, 安装dbms_random package

如果是8.1.5, 还需要在执行上面的语句之前, 执行:
execute dbms_random.initialize(1000); -- 其中1000为一个生成随机数的种子, 取任何值都可以.

 

 windff

 很好玩的SQL,dbms_random.random生成的一系列数字,不是什么列号,是作为一列来看待,如果SQL写成这样就容易理解了
select * from emp where empno in (select empno from (select empno,dbms_random.random a oder by a ) where rownum<3)
oder by 后面是可以跟一个常量的,这个常量被当作一个列来看待,
例如: select * from emp order by to_number('10')
是这样吗?
 
 
 oldwain

 有道理!

我原来钻牛角尖了, 总以为 order by 后面的数字一定是列号.

谢谢windff的解释, 这个问题让我绕了好长时间了.


 
 windff


 这个问题很好玩,这样的SQL不是很容易能见到的,也要感谢你了


 oldwain

 记得是92,93年前后, 看过一本有关occc(Obfuscated C Code Contest, 原版的)的书, 很有趣,
不知到有没有Obfuscated SQL Code Contest ?

以下是第一届occc的一段代码(相对后期的来说, 算很简单了), 对c有兴趣的, 不妨解释一番:


代码:--------------------------------------------------------------------------------
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hello, world!/n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
--------------------------------------------------------------------------------


下面的程序, 可以成为世上兼容性最好的程序, 它兼容c, fortran77, bourne shell !!!!!!!

代码:--------------------------------------------------------------------------------

cat =13 /*/ >/dev/null 2>&1; echo "Hello, world!"; exit
*
*  This program works under cc, f77, and /bin/sh.
*
*/; main() {
      write(
cat-~-cat
     /*,'(
*/
     ,"Hello, world!"
     ,
cat); putchar(~-~-~-cat); } /*
     ,)')
      end
*/

--------------------------------------------------------------------------------

 
 windff

 oldwin得好东西真多,看了上面的程序头都大,原来一直以为自己对c还算是知道的不少得,现在再看,简直什么都不知道,看杨振要好好学习了

 oldwain

 呵呵, 这与个人的水平无关.

要是很容易看懂, 就不能称为"Obfuscated "了.

下面是Obfuscated c 的入门程序片断, 要求在最快的时间(比如说10秒之内)内说出它的功能:


代码:--------------------------------------------------------------------------------
{   a = a + b;
   b = a - b;
   a = a -b;}
--------------------------------------------------------------------------------


 windff

 
真是让人糊涂的代码
其实就是吧a和b得值对调了一下,
真是佩服,为了少定义一个变量,竟然用到这样的办法,佩服啊
这书什么地方有,真想找来看看

 


 young107

 有趣的SQL,复杂的C语句,绕得我头都晕了。不过最后一段的功能好像是将A赋值为0。

 


 oldwain

 windff说得对, 这个方法确实比使用一个临时变量的效率要高!!!

想看更多的occc, 可以到http://www.ioccc.org/

有兴趣的话, 还可以去参加比赛(奖金情况我可不了解)

 


 
 windff

 谢谢oldwain,这样的问题有趣,能体验到乐趣,不象现在给客户开发的时候大多数时候是搬砖,一点乐趣都没有

 


 
 feng_xin

  不明白
select * from emp
where empno in ( select empno
from (select empno
from emp
order by dbms_random.random )
where rownum <= 3 )

1. dbms_random.random 返回一个随机数,那么order by dbms_random.random 应该相当于 order by '20'?
2. 若 select empno from emp order by '20' 的话,order by 启不是不起作用?
3.那么此SQL启不是永远返回前三条记录?

是不是这应该样写

select * from emp
where empno in ( select empno
from (select empno,dbms_random.random aa
from emp
order by aa)
where rownum <= 3 )

 


 
 
 oldwain

 两个语句应该是等价的.
注意:
1. 如果select empno from emp order by 20, 会出错(20 不是一个有效的列号),
但select empno from emp order by '20' 没有问题 (把'20'当作一个常量计算列)

2. order by dbms_random.random 应该相当于 order by '20' ?
不!
dbms_random.random 并不是只计算一次, 而是针对每一行计算一个, 所以得到的是一个变动的计算列, 而不是常量计算列.

做一下试验, 能够好的理解这之间的差异.


 
 internal

 这段C程序有味道啊,想起大学时好多同学都津津乐道于此的。

程序原来也可以编得像首诗呵。

  你站在桥上看风景,
  看风景的人在楼上看你。
  明月装饰了你的窗子,
  你装饰了别人的梦。
       ——卞之琳

 


 
 parrotao

 Add this topic to our E-magazine ?
It is very very very very funny, very very very exciting !!!
Thanks All


 
 
 oldwain

 呵呵, 把这篇帖子又给翻出来了?

我也很希望能做一些类似的小趣文放到e-mag里面.
可惜, 没有找到这方面的资源.
有没有人能提供一些有趣味sql(类似我上面提到的occc)的站点?


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值