ORA-01410 invalid ROWID某种情况

本文介绍ORA-01410错误的原因及解决办法,通常由于索引块损坏导致,可通过重建索引、导出导入表或使用CATS工具修复。文中还提供检查表和索引中ROWID有效性的命令。

 

select count(*) from tablename 时报:ORA-01410: invalid ROWID,以前从没出现过,什么原因?

ORA-01410 invalid ROWID
Cause: A ROWID was entered incorrectly. ROWIDs must be entered as formatted hexadecimal strings
using only numbers and the characters A through F. A typical ROWID format is ?00001F8.0001.0006?
Action: Check the format, then enter the ROWID using the correct format. ROWID format: block ID,
row in block, file ID
解决方式:
应该是索引块出了问题,rebuild一下就好了,最近的这个有些不一样。
是sqlldr通过direct方式加载,在维护索引的时候,如果此时机器突然死机,重启之后就会报出这样的错误,rebuild一下就可以了。
原贴地址:
http://www.itpub.net/98369.html

(1). CATS来解决
(2). 把这张表export/import一
(3).
解决ORA-01410:Invalid ROWID的一般步骤
===========================================================

1.使用ANALYZE TABLE <table> VALIDATE STRUCTURE CASCADE验证表和索引中的rowid是否有效.

2.设置event = "1410 trace name errorstack level 3" 跟踪,分析跟踪文件.
"

My suggestion:

1)do the above steps,

1)possibly the index of this table needs rebuild

2)data file corruption: use dbverify
Example
To verify the integrity of the data01.dbf data file, starting with block 1 and
ending with block 500, you execute the following command:
UNIX
$ dbv /users/DB00/u03/data01.dbf start=1 end=500

This should be similar to "analyze table"

Hope this is helpful.
## ❌ 错误信息:`ORA-00904: "A"."TROWID": invalid identifier` 这是一个 **Oracle 数据库的 SQL 语法错误**,意思是: > 在你的 SQL 查询中使用了列名 `"A"."TROWID"`,但 Oracle 找不到这个字段(列),因为它不存在或拼写错误。 --- ### 🔍 错误解释 ```text ORA-00904: "A"."TROWID": invalid identifier ``` - `"A"` 是你 SQL 中给表起的别名(table alias) - `"TROWID"` 是你试图访问的字段名 - Oracle 报错说明:**表 A 没有叫 `TROWID` 的列** ⚠️ 特别注意: - Oracle 有一个伪列叫做 `ROWID`(不是 `TROWID`)——用于唯一标识一行物理地址。 - 但你写的是 `TROWID`,这不是标准伪列,也不是常见命名,极可能是 **拼写错误** 或 **映射错误**。 --- ## 🧨 常见原因分析 ### ✅ 原因 1:字段名写错了(最常见) 你想查的是某个主键或业务 ID 字段,比如: | 正确字段名 | 误写为 | |----------|--------| | `TROW_ID` | `TROWID` ❌ | | `ROW_ID` | `TROWID` ❌ | | `ID` | `TROWID` ❌ | 👉 示例错误 SQL: ```sql SELECT a.trowid, a.company_name FROM T_ATML_COMPANY_BASE a WHERE a.trowid = '123'; ``` 如果实际字段是 `TROW_ID`,那就会报 `ORA-00904`。 --- ### ✅ 原因 2:实体类与数据库字段映射不一致(JPA/Hibernate 场景) 你在 Java 实体类中写了: ```java @Column(name = "TROWID") // 错误!数据库里其实是 TROW_ID private String trowId; ``` 而数据库真实字段是: ```sql TROW_ID VARCHAR2(50) ``` → Hibernate 生成 SQL 时会用 `a.TROWID`,但 Oracle 表中没有这个列 → 报错! --- ### ✅ 原因 3:使用了 `jdbcTemplate` + `BeanPropertyRowMapper` 自动映射 当你这样查询: ```java String sql = "SELECT * FROM T_ATML_COMPANY_BASE a"; List<AtmlCompanyBase> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(AtmlCompanyBase.class)); ``` `BeanPropertyRowMapper` 会尝试将查询结果中的字段按“驼峰转下划线”规则映射到对象属性。 例如: - Java 属性 `trowId` → 映射成数据库字段 `TROW_ID` - 如果你写成了 `trowid`(无下划线),它可能尝试匹配 `TROWID` → 出错! --- ### ✅ 原因 4:视图、同义词或表结构未同步 - 开发者在代码中假设存在 `TROWID` 字段 - 但实际上数据库表没加这个字段 - 或者部署脚本遗漏了 `ALTER TABLE ... ADD TROWID` 操作 --- ## ✅ 解决方案 ### ✅ 方案 1:检查并修正字段名(推荐) #### 第一步:查看表结构 运行以下 SQL 查看真实字段名: ```sql DESCRIBE T_ATML_COMPANY_BASE; -- 或 SELECT COLUMN_NAME FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'T_ATML_COMPANY_BASE'; ``` 输出示例: ``` COLUMN_NAME ----------- TROW_ID COMPANY_NAME STATUS_STR ... ``` 你会发现:**根本没有 `TROWID` 这个字段!** #### 第二步:修正为正确的字段名 ✅ 正确 SQL 应该是: ```sql SELECT a.trow_id, a.company_name FROM T_ATML_COMPANY_BASE a WHERE a.trow_id = '123'; ``` --- ### ✅ 方案 2:修改实体类字段映射 确保 Java 类中字段正确映射: ```java public class AtmlCompanyBase { @Column(name = "TROW_ID") // 显式指定真实字段名 private String trowId; public String getTrowId() { return trowId; } public void setTrowId(String trowId) { this.trowId = trowId; } } ``` 不要依赖自动转换,尤其是大小写敏感场景。 --- ### ✅ 方案 3:统一命名规范(长期建议) | Java 驼峰 | 数据库下划线 | |---------|-------------| | trowId | TROW_ID | | docTimeValidity | DOC_TIME_VALIDITY | | partyAccName | PARTY_ACC_NAME | 确保两者一致,避免映射失败。 --- ### ✅ 方案 4:启用 SQL 日志定位问题语句 在 `application.yml` 中开启: ```yaml logging: level: org.hibernate.SQL: DEBUG com.yourpackage: DEBUG ``` 然后重现错误,找到具体哪条 SQL 导致了 `a.trowid` 被引用。 --- ## ✅ 示例修复代码 假设你原来的错误出现在 JDBC 查询中: ❌ 错误代码: ```java String sql = "SELECT a.trowid, a.company_name FROM T_ATML_COMPANY_BASE a"; List<Map<String, Object>> result = jdbcTemplate.queryForList(sql); ``` ✅ 修正为: ```java String sql = "SELECT a.trow_id AS trow_id, a.company_name FROM T_ATML_COMPANY_BASE a"; List<Map<String, Object>> result = jdbcTemplate.queryForList(sql); ``` 或者使用别名匹配 Java 属性: ```java String sql = "SELECT a.trow_id AS trowId, a.company_name AS companyName FROM T_ATML_COMPANY_BASE a"; ``` --- ## ✅ 特别提醒:`ROWID` 是 Oracle 伪列,慎用! Oracle 内置伪列 `ROWID` 表示行的物理地址,你可以查: ```sql SELECT ROWID, company_name FROM T_ATML_COMPANY_BASE; ``` 但这不是业务主键,不能随便当 `id` 用。而且它和 `TROWID` 完全不同! --- ## ✅ 如何预防此类问题? | 方法 | 说明 | |------|------| | 使用 IDE 插件(如 MyBatis Plugin) | 自动校验 SQL 字段是否存在 | | 单元测试 + H2 模拟 Oracle | 提前发现字段映射问题 | | 统一使用 JPA 管理实体 | 避免手写 SQL 出错 | | 数据库变更走 DDL 脚本审核流程 | 确保字段真实存在 | --- ##
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值