您好!欢迎访问家园网-www.jy.wang!

家园网

这里给与了rownum列名,如果不给的话直接写行不行,直接用rownum>2?

网络 作者:本站 点击:

这里给与了rownum列名,如果不给的话直接写行不行,直接用rownum>2?

SELECT * FROM
(SELECT rownum no, goods_id, goods_name, shop_price
FROM goods)
WHERE no>2;


直接回答:不行。

你这个问题问得非常精准,正好踩中了 Oracle 中 ROWNUM 最经典的“坑”。

核心原因

ROWNUM 是在数据被取出的一瞬间才赋值的。 它并不是一个事先存在的固定编号。

当你执行 WHERE ROWNUM > 2 时,数据库的逻辑是这样的:

  1. 尝试取第一行数据,准备给这一行标记 ROWNUM = 1

  2. 检查条件:1 > 2不成立

  3. 于是这一行被丢弃

  4. 尝试取下一行数据,它仍然是准备被标记为 ROWNUM = 1(因为还没任何一行被成功取出)。

  5. 检查条件:1 > 2?还是不成立,再次丢弃。

  6. 循环往复,永远不会有任何一行能通过 ROWNUM > 2 的检查。

结果:直接写 WHERE ROWNUM > 2 会返回空集,一行数据都没有。


对比分析

你的写法逻辑结果
直接过滤
WHERE ROWNUM > 2
边取边编号边过滤,第一行就被 1>2 过滤掉了,导致整个查询取不到任何数据。报错/无数据 ❌
间接过滤
子查询先编号 AS no,再 WHERE no > 2
先把所有数据取出,并给每一行编上固定的号 no,然后再对这个已经存在的编号进行过滤。成功 ✅

类比理解

想象一下,你面前有一排人(数据),你要找出“排队位置大于2”的人。

  • 直接写 ROWNUM>2
    你对着第一个人问:“你是第几个?”
    他说:“我是第1个。”
    你说:“1不大于2,淘汰。” 然后直接让他走了。
    这时候,原本的第二个人就走到了第一个的位置。
    你再问他:“你是第几个?”
    他说:“我现在是第1个了。”
    你会发现,永远问不到第3个人,因为队伍一直在被淘汰,位置编号一直在变。

  • 用子查询先编号
    你让所有人先站好,拿出本子记录:“你叫1号,你叫2号,你叫3号...”。
    记录完毕,队伍不动了。
    然后你说:“编号大于2的站出来。”
    结果3号、4号...站了出来。


补充知识:ROWNUM 什么时候能用?

  • ✅ 可以用:WHERE ROWNUM = 1

    • 这是唯一能直接用的等值条件,常用于只取第一行。

  • ✅ 可以用:WHERE ROWNUM <= N (或 < N+1)

    • 用于取前N行(分页的第一步)。

  • ❌ 不能用:WHERE ROWNUM = N (N>1)

  • ❌ 不能用:WHERE ROWNUM > N

  • ❌ 不能用:WHERE ROWNUM BETWEEN A AND B

总结

你的直觉“想直接写”是很常见的想法,但在 Oracle 的 ROWNUM 机制下行不通。

结论:必须给 ROWNUM 起一个别名(如 no),把子查询的结果固化下来,然后再在外层用 WHERE no>2 过滤。 这也是你提供的正确代码能运行的原因


标签: