5

从应用程序用户执行以下 get_release 函数时,它返回正确的版本:12.1.3,但是当从另一个用户执行它时,它返回未知结果:

declare
l_release_name         varchar2(30);
l_other_release_info   varchar2(2000);
   begin
     if not apps.FND_RELEASE.get_release (l_release_name, l_other_release_info) then
         null;
     end if;
     dbms_output.put_line(l_release_name);
   end;

FND_RELEASE.get_release 是一个公共包,应该没有限制从另一个用户调用它。

在我在函数注释中找到的内容下方:

-- get_release() will usually return TRUE
  --  with RELEASE_NAME =
  --                    contents of RELEASE_NAME column in FND_PRODUCT_GROUPS
  --  and OTHER_RELEASE_INFO = null
  --
  -- If FND_PRODUCT_GROUPS.RELEASE_NAME contains imbedded spaces:
  --
  -- get_release() will return TRUE
  --  with RELEASE_NAME = FND_PRODUCT_GROUPS.RELEASE_NAME up to but
  --   not including the first imbedded space
  --  and OTHER_RELEASE_INFO = FND_PRODUCT_GROUPS.RELEASE_NAME
  --   starting with the first non-space character after the first
  --   imbedded space
  --
  -- On failure, get_release() returns FALSE. This will be a performance issue.
  --  Both RELEASE_NAME and OTHER_RELEASE_INFO will be set to 'Unknown'.
  --  This indicates that either:
  --  1) there are no rows in fnd_product_groups
  --     - this can be resolved by populating the row and it will
  --       be queried on the next call.
  --  2) there is more than one row in fnd_product_groups
  --     - delete all but the one correct row from fnd_product_groups and it
  --       will be queried on the next call. It's possible that the values
  --       returned by release_* and *_version routines are still correct if
  --       the first row in fnd_product_groups, ordered by product_group_id,
  --       if the currect row, but this will still be a performance problem.

以前有人遇到过这个问题吗?!

4

2 回答 2

1

我看到您正在使用 Oracle e-Business Suite 数据模型和包。

在该软件包中,FND_RELEASE被声明为AUTHID CURRENT_USER(即,它使用调用者的权限)。您可以在包装规范的第一行看到这一点。

这意味着FND_PRODUCT_GROUPS在此查询中查看的表...

select   release_name
from     fnd_product_groups
order by product_group_id;

...不是 APPS.FND_PRODUCT_GROUPS.. 它是FND_PRODUCT_GROUPS当前用户拥有的表。

由于该用户可能没有FND_PRODUCT_GROUPS表,因此在尝试运行该查询时会FND_RELEASE引发错误。ORA-00942: table or view does not exist

这会导致它跳到它的WHEN OTHERS异常处理程序,这会导致它返回 false 并将输出参数设置为“未知”。

解决此问题的一种方法是创建一个FND_RELEASE使用定义者权限的自定义包装器。像这样:

create or replace package xxcust_fnd_release AUTHID DEFINER IS

  function get_release (release_name       out nocopy varchar2,
                        other_release_info out nocopy varchar2)
  return boolean;
end xxcust_fnd_release;


create or replace package body xxcust_fnd_release IS

  function get_release (release_name       out nocopy varchar2,
                        other_release_info out nocopy varchar2)
  return boolean IS
  BEGIN
    return fnd_release.get_release (release_name, other_release_info);
  END;
end xxcust_fnd_release;

grant execute on xxcust_fnd_release to <your_other_username>;

如果您这样做,并按如下方式修改您的脚本,它将起作用:

declare
l_release_name         varchar2(30);
l_other_release_info   varchar2(2000);
   begin
     if not apps.XXCUST_FND_RELEASE.get_release (l_release_name, l_other_release_info) then
         null;
     end if;
     dbms_output.put_line(l_release_name);
   end;

替代解决方法

如果您不能或不想在架构中创建新的包装程序包,您可以在其他用户的架构中APPS创建同义词。FND_PRODUCT_GROUPS

例如,

create or replace synonym fnd_product_groups FOR apps.fnd_product_groups;

...在您的其他架构中执行此操作,您的原始脚本将起作用。

这种替代方案的缺点是 Oracle 补丁可能会更改逻辑FND_RELEASE以在其他表上引入其他查询,从而导致此解决方案中断,直到您创建所需的任何其他同义词。

于 2016-10-18T21:15:59.687 回答
1

据我所知有3种可能性:

  1. 使用invoker_rights_clause ( ) 编译的包FND_RELEASEAUTHID CURRENT_USERapps它为用户和任何其他用户使用不同的来源。
  2. 函数 FND_RELEASE.get_releasecontext用于访问。
  3. 在您的系统中使用的private database选项。它能够重写查询并向当前用户添加条件。(第 2 点的变化,但隐含)
于 2016-10-18T16:52:52.083 回答