Apex升级至23.1.5后报表抛出ORA-01445错误求助
问题:Apex升级至23.1.5后报表抛出ORA-01445错误
报表错误:
ORA-01445: cannot select ROWID from, or sample, a join view without a key-preserved table
将Apex升级到23.1.5版本后,一款此前运行正常的报表应用突然抛出上述错误。该模块用于展示数据,升级过程中未修改任何应用代码或配置,预期应用能保持升级前的运行状态。
后台查询代码如下:
SELECT s."ROWID", s."EMPLOYEE_NUMBER", NVL(p.full_name, 'Invalid') FULLNAME, s."DOCUMENT_TYPE", s."COST_CENTRE_PARENT", s."SIGNING_LIMIT", l.name ledger, a.organization_id FROM "#OWNER#".xxapex142_signing_limits s , apps.per_all_people_f p , apps.per_all_assignments_f a , apps.gl_ledgers l WHERE s.employee_number = p.employee_number (+) AND p.person_id = a.person_id (+) AND a.set_of_books_id = l.ledger_id (+) AND l.short_name = 'DJR_PRIMARY' AND ( UPPER(s.employee_number) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(p.full_name) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(s.cost_centre_parent) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(s.signing_limit) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(a.organization_id) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(l.name) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' )
解决方案
错误原因
ORA-01445错误的核心是:查询直接从多表连接的结果集中选择ROWID,但该结果集里没有Oracle认定的「键保留表」——也就是无法保证主表的每一行在连接后只出现一次,Oracle无法安全返回ROWID。Apex 23.1.5对报表查询的ROWID使用规则做了更严格的校验,升级前版本可能允许这种不规范写法,升级后触发了Oracle本身的约束检查。
修复步骤
1. 移除不必要的ROWID查询
如果报表不需要用ROWID做编辑、删除等操作,直接删掉SELECT列表中的s."ROWID"即可:
SELECT s."EMPLOYEE_NUMBER", NVL(p.full_name, 'Invalid') FULLNAME, s."DOCUMENT_TYPE", s."COST_CENTRE_PARENT", s."SIGNING_LIMIT", l.name ledger, a.organization_id FROM "#OWNER#".xxapex142_signing_limits s , apps.per_all_people_f p , apps.per_all_assignments_f a , apps.gl_ledgers l WHERE s.employee_number = p.employee_number (+) AND p.person_id = a.person_id (+) AND a.set_of_books_id = l.ledger_id (+) AND l.short_name = 'DJR_PRIMARY' AND ( UPPER(s.employee_number) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(p.full_name) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(s.cost_centre_parent) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(s.signing_limit) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(a.organization_id) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' OR UPPER(l.name) LIKE '%'||NVL(UPPER(:P2_SEARCH_TEXT),'')||'%' )
2. 若需唯一标识,改用业务主键
如果报表需要唯一标识用于后续操作,直接用s."EMPLOYEE_NUMBER"(假设该字段是xxapex142_signing_limits表的主键)替代ROWID,或者明确指定表的主键字段。
3. 确保连接结果存在键保留表
如果必须保留ROWID,需调整查询逻辑:
- 确认
s.employee_number是xxapex142_signing_limits表的主键或唯一约束,保证主表每行唯一 - 调整外连接逻辑,避免其他表的多行数据匹配到主表同一行
额外建议
- 升级Apex后,检查所有报表的ROWID使用情况,提前规避类似问题
- 多表连接查询中优先用业务主键,尽量避免直接使用ROWID
内容的提问来源于stack exchange,提问作者John T
相关产品推荐
相关产品推荐

