Oracle Forms调用PL/SQL过程报参数数量或类型错误咨询
Oracle Forms调用更新参数后的PL/SQL包报参数不匹配错误
问题复现
按以下步骤操作可在开发环境稳定复现异常:
- 第一步:创建包含单入参过程
TEST_PROC的PL/SQL包TEST,代码如下:
create or replace package test is procedure test_proc ( a varchar2); end test; / create or replace package body test is procedure test_proc ( a varchar2) IS BEGIN insert into temp (x) values (a); END; end test; /
- 第二步:在Forms的
When-button-pressed触发器中调用该过程,调用语句如下,此时可正常编译:
TEST.TEST_PROC('a');
- 第三步:因需求变更,为
TEST_PROC新增第二个varchar2类型入参,更新后的包代码如下,更新后在PL/SQL客户端中可正常编译运行:
create or replace package test is procedure test_proc ( a varchar2, b varchar2); end test; / create or replace package body test is procedure test_proc ( a varchar2, b varchar2) IS BEGIN insert into temp (x, y) values (a, b); END; end test; /
- 第四步:将
When-button-pressed触发器中的调用语句更新为双参数版本时,Forms抛出错误Wrong number or types of arguments in call to test_proc,报错时的调用语句如下:
TEST.TEST_PROC('a','b');
已尝试操作:关闭重启Forms、重新连接数据库、删除整个包后重建双参数版本,均未解决问题。
问题根因
报错与数据库端的包逻辑无关,是Oracle Forms固有缓存机制导致的:
- Forms不会实时同步数据库侧存储程序的元数据。第一次在Forms中调用数据库包时,Forms会将包头中的过程、函数签名缓存到当前模块的本地元数据存储中,后续编译触发器时会优先读取本地缓存的旧签名,不会主动拉取数据库端的最新定义。
- 重启Forms、重连数据库不会自动清空当前模块绑定的旧缓存,哪怕数据库端已经删除重建了包,只要本地缓存的旧签名未被清除,Forms就会一直按照最初缓存的单参数签名校验调用语句,最终抛出参数不匹配错误。
- 少数易忽略的场景:如果曾在Forms的本地程序单元(Program Units)节点下创建过同名的
TEST包或TEST_PROC过程,Forms编译时会优先调用本地程序单元,完全忽略数据库端的最新包定义。
解决方案
按优先级从高到低操作,绝大多数场景前两步即可解决问题:
- 强制全量编译刷新缓存:打开Forms Builder选中出问题的模块,点击顶部菜单栏
Program->Compile->Compile All,该操作会强制拉取所有引用数据库对象的最新元数据,重新编译所有触发器和程序单元。 - 手动刷新数据库对象引用:如果全量编译无效,在对象导航器中展开
Database Objects节点,找到当前连接用户下的TEST包,右键选择Refresh刷新对象定义,之后重新打开报错的触发器编译即可。 - 排查本地同名对象:展开导航器的
Program Units节点,检查是否存在同名的TEST包或TEST_PROC过程,如果存在直接删除——本地程序单元的引用优先级高于数据库对象,会直接覆盖数据库端的最新定义。 - 极端缓存异常处理:如果以上操作均无效,属于模块缓存写入损坏,将当前Forms模块导出为.fmt文本格式,关闭Forms Builder后重新打开,导入文本生成新的.fmb模块即可完全清除旧缓存,重新编译后即可正常调用。
内容的提问来源于stack exchange,提问作者Rashi
相关产品推荐
相关产品推荐

