【赵渝强老师】国产崖山数据库的行号:ROWNUM

b477

YashanDB 崖山数据库 ROWNUM 伪列

YashanDB 的 ROWNUM 伪列,行为高度类似 Oracle,仅单机/主备、共享集群可用;存算一体分布式集群不能使用 ROWNUM。
ROWNUM:查询返回的行,系统顺序分配编号,第一行=1,逐行递增;是先分配行号,再做过滤。

image.png
点击这里查看视频讲解:【赵渝强老师】国产崖山数据库的行号:ROWNUM

✅ 基础语法(HEAP行存表,最常用)

-- 查出前5行
SELECT t.*, ROWNUM FROM emp t WHERE ROWNUM <=5;

# 输出的信息如下:
 EMPNO ENAME         JOB           MGR HIREDATE         SAL   COMM   DEPTNO  ROWNUM 
------ ------------- ---------- ------ ------------- ------ ------ -------- ------- 
  7369 SMITH         CLERK        7902 1980/12/17       800              20       1
  7499 ALLEN         SALESMAN     7698 1981/2/20       1600    300       30       2
  7521 WARD          SALESMAN     7698 1981/2/22       1250    500       30       3
  7566 JONES         MANAGER      7839 1981/4/2        2975              20       4
  7654 MARTIN        SALESMAN     7698 1981/9/28       1250   1400       30       5

5 rows fetched.

-- 只取第1行
SELECT * FROM emp WHERE ROWNUM = 1;

# 输出的信息如下:
 EMPNO ENAME         JOB           MGR HIREDATE         SAL   COMM   DEPTNO  ROWNUM 
------ ------------- ---------- ------ ------------- ------ ------ -------- ------- 
  7369 SMITH         CLERK        7902 1980/12/17       800              20       1

-- ROWNUM>1 直接返回空!重点坑
SELECT * FROM emp WHERE ROWNUM >1; -- ❌ 无结果

# 输出的信息如下:
 EMPNO ENAME         JOB           MGR HIREDATE         SAL   COMM   DEPTNO  ROWNUM 
------ ------------- ---------- ------ ------------- ------ ------ -------- ------- 

原理:ROWNUM 是动态分配,必须先有 ROWNUM=1 的行满足条件,才会继续生成2、3;如果条件 ROWNUM>1,第一行ROWNUM=1不满足,直接丢弃,永远不会生成2。

✅ 排序后分页(一定要子查询!)

⚠️ 坑:WHERE ROWNUM <=10 AND ORDER BY col,ROWNUM 在排序前分配,不是排序后的行号!
正确写法:内层先排序,外层再分配行号

select rownum,ename,sal
from (select * from emp order by sal desc)
where rownum<=5;

# 输出的信息如下:

ROWNUM 	ENAME     SAL
------------------- --------------- ----------
 1 		KING 	    5000
 2 		SCOTT	    3000
 3 		FORD 	    3000
 4 		JONES	    2975
 5 		BLAKE	    2850

✅ 分页:取第6~10行(Oracle风格分页)

SELECT * FROM (
    SELECT t.*, ROWNUM rn
    FROM (
        SELECT * FROM emp ORDER BY sal DESC
    ) t
) WHERE rn >=6 AND rn <=10;

# 输出的信息如下:
 EMPNO ENAME    JOB          MGR HIREDATE       SAL   COMM   DEPTNO    RN 
------ -------- --------- ------ ----------- ------ ------ -------- ----- 
  7782 CLARK    MANAGER     7839 1981/6/9      2450              10     6
  7499 ALLEN    SALESMAN    7698 1981/2/20     1600    300       30     7
  7844 TURNER   SALESMAN    7698 1981/9/8      1500              30     8
  7934 MILLER   CLERK       7782 1982/1/23     1300              10     9
  7521 WARD     SALESMAN    7698 1981/2/22     1250    500       30    10

5 rows fetched.

✅ 窗口函数 ROW_NUMBER()(推荐,不受ROWNUM限制)

如果需要稳定排序行号、复杂分页,优先用窗口函数 ROW_NUMBER(),分布式集群也支持:

SELECT 
    t.*,
    ROW_NUMBER() OVER(ORDER BY sal DESC) AS rn
FROM emp t;

# 输出的信息如下:
 EMPNO ENAME    JOB           MGR HIREDATE        SAL  COMM  DEPTNO    RN 
------ -------- ---------- ------ ------------ ------ ----- ------- ----- 
  7839 KING     PRESIDENT      -1 1981/11/17     5000            10     1
  7788 SCOTT    ANALYST      7566 1987/4/19      3000            20     2
  7902 FORD     ANALYST      7566 1981/12/3      3000            20     3
  7566 JONES    MANAGER      7839 1981/4/2       2975            20     4
  7698 BLAKE    MANAGER      7839 1981/5/1       2850            30     5
  7782 CLARK    MANAGER      7839 1981/6/9       2450            10     6
  7499 ALLEN    SALESMAN     7698 1981/2/20      1600   300      30     7
  7844 TURNER   SALESMAN     7698 1981/9/8       1500            30     8
  7934 MILLER   CLERK        7782 1982/1/23      1300            10     9
  7521 WARD     SALESMAN     7698 1981/2/22      1250   500      30    10
  7654 MARTIN   SALESMAN     7698 1981/9/28      1250  1400      30    11
  7876 ADAMS    CLERK        7788 1987/5/23      1100            20    12
  7900 JAMES    CLERK        7698 1981/12/3       950            30    13
  7369 SMITH    CLERK        7902 1980/12/17      800            20    14

14 rows fetched.


分页示例:

SELECT * FROM (
    SELECT 
        t.*,
        ROW_NUMBER() OVER(ORDER BY sal DESC) AS rn
    FROM emp t
) WHERE rn between 6 and 10;

# 输出的信息如下:
 EMPNO ENAME   JOB         MGR HIREDATE     SAL  COMM  DEPTNO   RN 
------ ------- --------- ----- ---------- ----- ----- ------- ---- 
  7782 CLARK   MANAGER    7839 1981/6/9    2450            10    6
  7499 ALLEN   SALESMAN   7698 1981/2/20   1600   300      30    7
  7844 TURNER  SALESMAN   7698 1981/9/8    1500            30    8
  7934 MILLER  CLERK      7782 1982/1/23   1300            10    9
  7521 WARD    SALESMAN   7698 1981/2/22   1250   500      30   10

5 rows fetched.

⚠️ 列存表(COLUMN表)ROWNUM 强限制(非常重要)

列存表使用 ROWNUM 约束极多:

  1. ROWNUM 只能和常量比较
  2. WHERE里不能用 >、<、>=、<=
  3. 等值比较只能等于常量1,ROWNUM=2 直接返回空
  4. 不能放在 OR 条件、不能参与运算、不能作为函数参数
  5. 不能在外连接的连接条件使用

👉 列存表不要用ROWNUM做分页,改用ROW_NUMBER窗口函数

✅ YashanDB 原生分页语法(推荐新写法,类似MySQL limit offset)

YashanDB 支持 FETCH / OFFSET,更简洁:

-- 取前5行
SELECT * FROM emp ORDER BY sal DESC FETCH FIRST 5 ROW ONLY;

# 输出的信息如下:
  EMPNO ENAME   JOB          MGR HIREDATE        SAL  COMM  DEPTNO 
------- ------- ---------- ----- ------------ ------ ----- ------- 
   7839 KING    PRESIDENT     -1 1981/11/17     5000            10
   7902 FORD    ANALYST     7566 1981/12/3      3000            20
   7788 SCOTT   ANALYST     7566 1987/4/19      3000            20
   7566 JONES   MANAGER     7839 1981/4/2       2975            20
   7698 BLAKE   MANAGER     7839 1981/5/1       2850            30

5 rows fetched.

-- 跳过3行,取4行(offset从0开始)
SELECT * FROM emp ORDER BY sal DESC OFFSET 3 ROW FETCH FIRST 4 ROW ONLY;

# 输出的信息如下:
 EMPNO ENAME   JOB          MGR HIREDATE     SAL   COMM  DEPTNO 
------ ------- --------- ------ ---------- ----- ------ ------- 
  7566 JONES   MANAGER     7839 1981/4/2    2975             20
  7698 BLAKE   MANAGER     7839 1981/5/1    2850             30
  7782 CLARK   MANAGER     7839 1981/6/9    2450             10
  7499 ALLEN   SALESMAN    7698 1981/2/20   1600    300      30

4 rows fetched.

📌 ROWNUM常见错误汇总

  1. WHERE ROWNUM = 2 → 空结果 ✘
  2. WHERE ROWNUM > 1 → 空结果 ✘
  3. WHERE ROWNUM <=10 ORDER BY xxx → 行号是排序之前分配,不是排序后的行号 ✘
  4. 分布式集群直接写ROWNUM → 语法报错 ✘
  5. 列存表 ROWNUM <=10 → 不支持 ✘

📌 ROWNUM vs ROW_NUMBER() vs FETCH

对象 适用场景 集群支持 说明
ROWNUM伪列 单机/主备/共享集群,行存HEAP表 ❌分布式 轻量取前N行;分页需要嵌套子查询
ROW_NUMBER()窗口函数 全部部署形态,行存/列存 ✅分布式 排序后生成行号,分页首选
OFFSET ... FETCH 全部部署形态 ✅分布式 简洁分页,推荐新项目
posted @ 2026-10-15 10:49  赵渝强老师  阅读(6)  评论(0)    收藏  举报