【问题标题】:oracle "table or view does not exist" from inside stored procedure存储过程中的oracle“表或视图不存在”
【发布时间】:2011-05-11 00:41:13
【问题描述】:

剧情是这样的……

我有一个命名空间XXX,我在其中创建了一些表和一些存储过程...

他们有一个命名空间YYY,他们在其中创建了一些表...

他们授予XXX 访问他们的表的权限,所以当我使用XXX 连接到 SQL Developer 时,我可以这样做:

SELECT * FROM YYY.TableA

但是,如果我尝试从存储过程(简单存储过程或包)内部运行相同的语句,则存储过程不会编译。很多sp都会遇到这种情况。还有其他我必须要求的许可吗???我是这样运行 sp 的:

CREATE OR REPLACE PROCEDURE PRC_SOMESP(
) AS BEGIN
END PRC_SOMESP;

不访问 YYY 表的过程编译得很好。

提前致谢。

在 Justin Cave 响应之后,我尝试将“AUTHID CURRENT_USER”语句添加到 sp,但得到相同的“表或视图不存在”结果:

CREATE OR REPLACE PROCEDURE PRC_PROC1( PARAMETERS... )  
AUTHID CURRENT_USER  
AS  
    MYVAR NUMBER;  
BEGIN  
    STATEMENTS...
END PRC_PROC1;  

CREATE OR REPLACE PACKAGE PKG_PROC2  
AUTHID CURRENT_USER  
AS  
TYPE T_CURSOR IS REF CURSOR;
PROCEDURE PRC_PROC2( PARAMETERS... )  
END PKG_PROC2  

我应该检查其他的吗???

【问题讨论】:

  • 首先,您不会像您说的那样运行 SP,而是创建它们。其次,确保PRC_SOMESP() 拥有比YYY.TableA 更合适的权限以从中进行选择。

标签: oracle stored-procedures


【解决方案1】:

很可能,问题在于授权是通过角色完成的。授予用户的权限在定义者权限存储过程(默认)中不可用。

在 SQL Developer 中,验证这是否是问题相对容易。如果你运行命令

SET ROLE none

然后运行 ​​SELECT 语句,我希望你会得到同样的 ORA-00942 错误。

假设是这种情况,解决方案通常是要求 YYY 模式中的表的所有者直接向您授予对表的访问权限,而不是通过角色授予访问权限。除此之外,您可以通过将 AUTHID CURRENT_USER 添加到声明中来将您的存储过程定义为调用者的权限存储过程。这意味着过程的调用者需要访问底层对象,但它会允许您的过程使用通过角色授予的权限。

如果要创建调用者权限存储过程,还需要使用动态 SQL 引用表名,以便将权限检查推迟到运行时。所以你会有类似的东西

CREATE OR REPLACE PROCEDURE PRC_SOMESP 
  AUTHID CURRENT_USER
AS 
  l_cnt pls_integer;
BEGIN
  EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM yyy.TableA' INTO l_cnt;
END PRC_SOMESP;

如果您想要一个调用者权限存储过程来查询架构 XXX 中的 TableA 表。

【讨论】:

  • 是的,这正是贾斯汀的问题……你能不能通过添加“AUTHID CURRENT_USER”这句话来写下存储过程声明应该是怎样的?我阅读了其他链接,但找不到示例:articles.techrepublic.com.com/5100-10878_11-6183799.html
  • @user509925 - 将示例添加到我的答案中。
  • @user509925 - 很抱歉。我上次的更新很不正确。您需要使用动态 SQL 将权限检查推迟到运行时,此时 AUTHID CURRENT_USER 允许 Oracle 使用通过角色授予的权限。更新了我的答案以反映这一点。
  • ups.. 无法执行动态 sql... 我正在将存储过程更改为普通查询... 这个 Oracle 的东西正在成为一个折磨人。谢谢你的回答贾斯汀......我认为 Stackoverflow 还没有让我给分(特权,ja),所以,很抱歉
  • @JustinCave 我遇到了类似的问题,当我使用您的解决方案时,我最终在绝对 URI 中遇到相对路径错误。这是这种技术的常见问题吗?
【解决方案2】:

在架构 XXX 上的存储过程中,如果您从 YYY 架构访问表,请确保完全限定它们:

select count(1) from YYY.TableA;

要考虑的其他事项是大小写(以防您在 Oracle 标识符中混合大写和小写)。

最后一件事:发布您遇到的错误。这样会更容易为您提供帮助。

【讨论】:

  • 例如,如果您的数据库对每个客户都有一个模式,则此解决方案可以工作,但不会很优雅。每个客户都需要一个版本的相同 SP 才能为他们每个人工作。
【解决方案3】:

我也遇到了同样的问题。我不是 DBA,但向我解释的方式是“基本的事情是您的个人角色权限在存储过程中无效。”

有人建议我用表的所有者来限定 SP 的名称,如下所示:

CREATE OR REPLACE PROCEDURE yyy.PRC_PROC1( PARAMETERS... ) etc

这适用于我的开发环境。我的环境只有一个命名空间,所以我不确定这是否能解决 OP 的问题,但希望有助于为下一个查找此问题的 18000 人推动这个问题;-)。

另外,当我将我的 SP 投入生产时,我需要删除限定符,我们的安装软件将在适当的权限下运行 create。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多