在DBMS_AQ的enqueue方法的Oracle文档中,指定“对象的名称由可选的模式名称和名称指定。如果未指定模式名称,则假定当前模式< /强>“。 [1]
有问题的系统定义了模式中的所有对象,我们称之为DEV。然后将用户定义为DEV_AD,并且在登录期间,有一个触发器ALTER SESSION将其当前架构发送到DEV。这意味着当他们从sometable中选择*时,他们从DEV.sometable中选择*,而不是DEV_AD.sometable。这没有问题。
但是,当用户尝试在SOMEQUEUE上排队消息时,它不起作用 - 系统会尝试将不存在的DEV_AD.SOMEQUEUE排队,而不是DEV.SOMEQUEUE。通过将DEV.SOMEQUEUE而不仅仅是SOMEQUEUE作为DBMS_AQ.ENQUEUE的参数放置,消息成功排队。
这是Oracle错误(或文档错误),是否有解决方法?
如果这是一个错误,我们仍然会在接下来的几个月内使用10.2.0.4.0。它固定在11g?
[1] http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_aq.htm#ARPLS081
答案 0 :(得分:1)
在进一步搜索Oracle支持之后,这是一个错误 - 请参阅Metalink中的Doc ID 220477.1。
它已在11.2.0.2中修复;此公开链接包含更多信息:https://community.oracle.com/thread/846141但该修复程序对我们无效。
答案 1 :(得分:1)
鉴于这是错误1259821并且事件变通方法不适合您或者实际上不实用,您的另一个选择是通过指定模式名称来完全限定队列名称。据推测,您试图避免在AQ调用中对模式名称进行硬编码,例如:
dbms_aq.enqueue(queue_name => 'DEV.SOMEQUEUE', ...);
...因为您拥有跨环境共享的公共代码,并且您希望在运行时使用正确的模式/队列,具体取决于登录触发器设置的模式。
如果是这种情况,那么您可以使用当前架构指定完整队列名称:
dbms_aq.enqueue(queue_name =>
sys_context('USERENV', 'CURRENT_SCHEMA') || '.SOMEQUEUE', ...);
在运行时,对于DEV_AD
用户,仍然会将'DEV.SOMEQUEUE'
作为队列名称传递。
ad hoc代码中有点痛苦(如果你是从匿名块调用的话),但是如果从存储过程排队则不会太糟糕。从错误描述来看,它似乎只是存储代码中的一个问题,因为定义者/调用者权限与匿名块无关。