YashanDB 崖山数据库 ROWNUM 伪列
YashanDB 的 ROWNUM 伪列,行为高度类似 Oracle,仅单机/主备、共享集群可用;存算一体分布式集群不能使用 ROWNUM。
ROWNUM:查询返回的行,系统顺序分配编号,第一行=1,逐行递增;是先分配行号,再做过滤。
视频讲解如下:
✅ 基础语法(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 约束极多:
- ROWNUM 只能和常量比较
- WHERE里不能用 >、<、>=、<=
- 等值比较只能等于常量1,ROWNUM=2 直接返回空
- 不能放在 OR 条件、不能参与运算、不能作为函数参数
- 不能在外连接的连接条件使用
👉 列存表不要用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常见错误汇总
- WHERE ROWNUM = 2 → 空结果 ✘
- WHERE ROWNUM > 1 → 空结果 ✘
- WHERE ROWNUM <=10 ORDER BY xxx → 行号是排序之前分配,不是排序后的行号 ✘
- 分布式集群直接写ROWNUM → 语法报错 ✘
- 列存表 ROWNUM <=10 → 不支持 ✘
📌 ROWNUM vs ROW_NUMBER() vs FETCH