19.oracle伪列

一、ROWID伪列

        数据表中每一行所保存的记录,Oracle都会默认为每条记录分配一个唯一的地址编号,这个地址编号就是ROWID。

1.1 查询ROWID      

select rowid,deptno,dname,loc from dept;

        ROWID保存着该条数据数据对象号(表空间)、相对文件号(文件)、数据块号(数据块)和数据行号(行)信息,以便在插叙数据时能够准确快速的定位到数据。

1.2 利用ROWID删除重复数据

        假设由于误操作在数据库表dept种存在了很多很多重复性的数据:

        如上面表格中红色圈出的部分,由于后面添加的数据的ROWID要大于之前数据的ROWID,可以利用这点对重复数据进行删除:
delete from dept where rowid 
not in
(select min(rowid) from dept group by deptno);
        删除后的效果如下:

二、ROWNUM伪列

        rownum是一个数据行编号的伪列,用户在查询数据时,oracle会为每一行分配一个数字表示行号。

2.1 查询时为每行实现分配一个行号


2.2 利用ROWNUM实现分页

        如果我们有需求需要查询出dept表中第3条和第4条数据,我们可以利用rownum作为查询条件进行实现,但是rownum作为查询条件时不能放在>号的右边,也就是说不能出现>rownum或者>=rownum的字样,如下面的列子,按照普通的查询方法,我们查询第3和4行数据:
select * from dept where rownum<=4 and rownum>=3;
        发现查询结果为空,原因时oracle在进行查询时会从数据表中逐行进行判断,当判断到:
        第1行,rownum为1,不符合条件,此时第2行会变成第1行,以此类推,因此得到了一个空的结果集。
        真正的做法是利用子查询和rownum进行分页查询:
select * from
(select rownum rn,deptno,dname,loc from dept where rownum<=4)
where rn>=3; 













































<think>我们正在讨论Oracle中的ROWNUM伪列。根据引用内容,ROWNUM确实是Oracle数据库中的伪列。以下是详细的解释: 1. **伪列的定义**:伪列(Pseudo-column)是Oracle数据库中一种特殊的列,它并不是表中实际存储的列,但可以在查询中像普通列一样使用。ROWNUM就是这样一个伪列,它会在查询结果返回时为每一行分配一个从1开始的连续整数。 2. **ROWNUM的特性**: - **动态生成**:ROWNUM是在查询过程中动态生成的,它表示结果集中行的顺序号,从1开始递增。 - **排序前分配**:ROWNUM是在数据被检索出来之后,但在排序(ORDER BY)之前分配的(引用[3]提到:“生成ROWNUM操作比排序要早”)。因此,如果先进行排序,ROWNUM的顺序可能与排序后的顺序不一致。 3. **使用限制**: - 由于ROWNUM是从1开始连续递增的,所以当使用`ROWNUM > n`(n>1)条件时,将无法返回任何结果(引用[1]中解释了原因:没有前面的行,后面的行就不会存在,就像没有1楼就不会有10楼)。 - 因此,在分页查询中,通常使用子查询先获取一个带有ROWNUM的结果集(并给ROWNUM起别名),然后在外部查询中使用这个别名进行范围筛选(如引用[2]所示)。 4. **与排序结合使用**:要获取排序后的前N条记录,需要先排序,然后对排序后的结果使用ROWNUM(引用[3]中提到需要对排序结果做二次查询,产生新的ROWNUM)。 因此,回答用户的问题:**是的,Oracle数据库中的ROWNUM伪列。** **示例说明**: 假设我们想查询员工表中工资最高的前5名,直接使用以下方式是不正确的: ```sql SELECT * FROM employees WHERE ROWNUM <= 5 ORDER BY salary DESC; ``` 因为ROWNUM在排序前就已经分配了,这样得到的是原始顺序的前5条记录,然后对这5条记录按工资降序排序,可能并不是工资最高的5个。 正确做法(使用子查询先排序,再使用ROWNUM): ```sql SELECT * FROM ( SELECT * FROM employees ORDER BY salary DESC ) WHERE ROWNUM <= 5; ``` **相关注意事项**: - 在子查询中排序后,外层查询使用ROWNUM<=5来获取前5条。 - 如果需要处理并列情况(比如第5名有多个),则可能需要使用窗口函数(如DENSE_RANK())而不是简单的ROWNUM。 **引用**: [^1]: Oracle中的伪列ROWNUMOracle中的利用伪列ROWNUM分页查询。 [^2]: oracle表中的伪列,Oracle数据库的伪列rownum的使用方法。 [^3]: Oracle伪列rownum。 §§相关问题§§ 1. Oracle中除了ROWNUM还有哪些伪列? 2. 如何使用ROWNUM实现分页查询? 3. ROWNUMROWID有什么区别? 4.Oracle 12c及以上版本中,是否有更好的方法替代ROWNUM进行分页?</think>是的,**Oracle数据库中的ROWNUM确实是伪列**。根据引用内容,以下是关键说明: ### ROWNUM作为伪列的核心特性 1. **动态生成性** ROWNUM不是物理存储在表中的真实列,而是**查询执行时动态生成的虚拟序列**(引用[1][^1])。它会在数据检索后自动附加到结果集上,从1开始连续递增: ```sql SELECT ROWNUM, employee_id, first_name FROM employees; -- 输出示例: -- ROWNUM | employee_id | first_name -- 1 | 101 | John -- 2 | 102 | Jane ``` 2. **严格递增特性** ROWNUM**永远从1开始连续分配**,无法跳过起始值(引用[1][^1])。这解释了为什么以下查询无效: ```sql -- 错误示例(永远返回空结果) SELECT * FROM (SELECT ROWNUM rn, t.* FROM employees t) WHERE rn > 10 AND rn < 20; ``` 原因:没有1-9层的"楼房",就不可能存在10层(引用[1][^1]的楼房比喻)。 3. **执行顺序依赖** ROWNUM在**排序前分配**(引用[3][^3]),导致直接结合`ORDER BY`会出错: ```sql -- 错误:实际返回原始顺序的前5行,而非工资最高的5人 SELECT ROWNUM, employee_id, salary FROM employees WHERE ROWNUM <= 5 ORDER BY salary DESC; ``` ### 正确使用ROWNUM的方法 1. **分页查询解决方案** 通过嵌套子查询使ROWNUM"实体化"(引用[2][^2]): ```sql -- 查询第11-19条记录 SELECT * FROM ( SELECT ROWNUM rn, t.* FROM employees t WHERE ROWNUM < 20 -- 先限制上限 ) WHERE rn > 10; -- 后筛选下限 ``` 2. **Top-N查询解决方案** 先排序再应用ROWNUM(引用[3][^3]): ```sql -- 获取工资最高的前5名 SELECT * FROM ( SELECT * FROM employees ORDER BY salary DESC ) WHERE ROWNUM <= 5; ``` ### 伪列 vs 真实列 | 特性 | ROWNUM (伪列) | 真实列 (如employee_id) | |--------------|------------------------|------------------------| | 存储方式 | 动态生成,不占存储空间 | 物理存储在表中 | | 值稳定性 | 每次查询重新生成 | 持久不变 | | 可更新性 | ❌ 不可插入/修改 | ✔️ 可DML操作 | | 查询条件限制 | 不能直接使用`>` | 无限制 | ### 总结 ROWNUM作为Oracle核心伪列,其本质是**查询运行时生成的动态行序号**。理解其"从1连续递增"和"在排序前分配"的特性(引用[1][^1][^3]),是避免分页/Top-N查询错误的关键。在需要跳过起始行的场景中,必须通过嵌套子查询使其"实体化"(引用[2][^2])。 [^1]: Oracle中的伪列ROWNUMOracle中的利用伪列ROWNUM分页查询。 [^2]: oracle表中的伪列,Oracle数据库的伪列rownum的使用方法。 [^3]: Oracle伪列rownum
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值