为什么我的查询在程序(PL/SQL)中不返回记录,但在SQL中手动运行时却返回记录?

为什么我的查询在程序(PL/SQL)中不返回记录,但在SQL中手动运行时却返回记录?,sql,oracle,plsql,Sql,Oracle,Plsql,大家好,谢谢你们抽出时间来帮助我 我有以下疑问: SELECT owner, object_name FROM all_objects WHERE owner IN ('EDI') ORDER BY object_type, object_name; 正如您在屏幕截图中看到的,它返回一些值 当我从程序内部调用查询时,它不会返回任何值(参见第二个屏幕截图) 用于说明这一点的测试代码是: CREATE OR REPLACE PROCEDURE my_test AS BEGIN

大家好,谢谢你们抽出时间来帮助我

我有以下疑问:

SELECT   owner, object_name
FROM     all_objects
WHERE    owner IN ('EDI')
ORDER BY object_type, object_name;

正如您在屏幕截图中看到的,它返回一些值

当我从程序内部调用查询时,它不会返回任何值(参见第二个屏幕截图)

用于说明这一点的测试代码是:

CREATE OR REPLACE PROCEDURE my_test
AS
BEGIN
    DBMS_OUTPUT.put_line('Pre-Loop');

    FOR indx IN (SELECT   owner, object_name
                 FROM     all_objects
                 WHERE    owner IN ('EDI')
                 ORDER BY object_type, object_name)
    LOOP
        DBMS_OUTPUT.put_line('Object: ' || indx.owner || '.' || indx.object_name);
    END LOOP;

    DBMS_OUTPUT.put_line('Post-Loop');
END;
/

BEGIN
    my_test();
END;
/
EDI模式是全新的,因此我怀疑这是一个授权/特权问题,但我似乎无法找到我可能缺少的内容,以便使其正常工作。我已经试着以EDI用户和SYS的身份运行这个

在得到答案后进行编辑

我在一篇评论中提到,要找到这个问题的官方答案的替代方案,并希望确保稍后阅读本文的任何人都能分享,以便他们能够权衡同样的决定


向预期运行代码的用户应用授权,如执行任何程序或选择任何表格,都会起作用,但我确信有理由不给予如此广泛的授权。

这就是你现在拥有的-根本没有结果:

SQL> CREATE OR REPLACE PROCEDURE my_test
  2  AS
  3  BEGIN
  4      DBMS_OUTPUT.put_line('Pre-Loop');
  5
  6      FOR indx IN (SELECT   owner, object_name
  7                   FROM     all_objects
  8                   WHERE    owner IN ('SCOTT')
  9                     AND    rownum < 5               -- you don't have that
 10                   ORDER BY object_type, object_name)
 11      LOOP
 12          DBMS_OUTPUT.put_line('Object: ' || indx.owner || '.' || indx.object_name);
 13      END LOOP;
 14
 15      DBMS_OUTPUT.put_line('Post-Loop');
 16  END;
 17  /

Procedure created.

SQL> BEGIN
  2      my_test();
  3  END;
  4  /

PL/SQL procedure successfully completed.

您的存储过程是定义者权限存储过程。这意味着它不能访问通过角色授予的特权,只能访问直接授予过程所有者的特权。另一方面,除了用户的直接授权外,Ad-hoc-SQL还以当前会话中启用的任何角色的权限运行。最有可能的是,过程的所有者可以通过角色而不是直接授权访问相关的表

您可以通过运行

set role none;
然后运行特设SQL语句。如果我的赌注是正确的,那么由于您已禁用了会话的所有角色,特设SQL现在将返回0行

根据您将对该过程执行的操作,您可以通过将其转换为调用者权限存储过程来解决问题

CREATE OR REPLACE PROCEDURE my_test
  AUTHID CURRENT_USER
AS

这将导致过程以调用方会话的权限(包括通过角色授予的权限)而不是定义方的权限运行。假设您要调用该过程的所有用户都有权访问
EDI
表,这就足够了。

嗨,Justin,这对我的测试起到了作用,我犯的错误是没有让人知道我的实际问题是存储在包中的过程。为了方便演示这个问题,我做了一个单独的过程,但是这个AUTHID CURRENT_USER语句似乎只能在顶层使用,所以我必须将它放在整个包中。我还不知道我对此有何感想。我对补助金和特权不是很精通。我确实找到了另一种方法,但我不确定我想用哪种方法。看来我得到了我需要的,只需要决定一个选项。@bunchesbunches-授予
选择任何表
执行任何过程
在任何类型的安全审计中都将是一个巨大的危险信号。如果在您的用例中使用invoker的权限是不合适的,那么直接授予过程所有者对
EDI
模式表的访问权,而不是通过角色,将更有意义。
CREATE OR REPLACE PROCEDURE my_test
  AUTHID CURRENT_USER
AS