Oracle 存储过程未返回正确的结果

Oracle 存储过程未返回正确的结果,oracle,stored-procedures,plsql,Oracle,Stored Procedures,Plsql,我有一个这样的存储过程 CREATE OR REPLACE PROCEDURE schema_name.CHECKS IS tbl_name VARCHAR2 (50); constraint_nm VARCHAR2 (100); CURSOR cur_constraint IS SELECT DISTINCT table_name, constraint_name FROM all_constraints WH

我有一个这样的存储过程

CREATE OR REPLACE PROCEDURE schema_name.CHECKS
IS
   tbl_name        VARCHAR2 (50);
   constraint_nm   VARCHAR2 (100);
   CURSOR cur_constraint
   IS
      SELECT DISTINCT table_name, constraint_name
        FROM all_constraints
       WHERE     constraint_type = 'R'
             AND STATUS = 'ENABLED'
             AND R_OWNER = 'owner1'
             AND r_constraint_name = 'constraint1';
BEGIN
   DBMS_OUTPUT.put_line ('Constraint Name');
   OPEN cur_constraint;
   LOOP
      FETCH cur_constraint
      INTO tbl_name, constraint_nm;
      EXIT WHEN cur_constraint%NOTFOUND;
      DBMS_OUTPUT.put_line (constraint_nm||'~~'||tbl_name);
   END LOOP;
   close cur_constraint;
END CHECKS;
DECLARE
   tbl_name        VARCHAR2 (50);
   constraint_nm   VARCHAR2 (100);
   CURSOR cur_constraint
   IS
      SELECT DISTINCT table_name, constraint_name
        FROM all_constraints
       WHERE     constraint_type = 'R'
             AND STATUS = 'ENABLED'
             AND R_OWNER = 'owner1'
             AND r_constraint_name = 'constraint1';
BEGIN
   FOR i IN cur_constraint
   LOOP
      EXIT WHEN cur_constraint%NOTFOUND;
      DBMS_OUTPUT.put_line (i.constraint_name||' is in '||i.table_name);
   END LOOP;
END;
我通过

set serveroutput on

BEGIN
   schema_name.CHECKS ();
END;
我得到的结果是

Procedure created.
Constraint Name
PL/SQL procedure successfully completed.
它不返回任何结果,但理想情况下应该返回一行(用于定义游标的select查询将返回一行)

当我像这样以PL/SQL块的形式执行上述代码时

CREATE OR REPLACE PROCEDURE schema_name.CHECKS
IS
   tbl_name        VARCHAR2 (50);
   constraint_nm   VARCHAR2 (100);
   CURSOR cur_constraint
   IS
      SELECT DISTINCT table_name, constraint_name
        FROM all_constraints
       WHERE     constraint_type = 'R'
             AND STATUS = 'ENABLED'
             AND R_OWNER = 'owner1'
             AND r_constraint_name = 'constraint1';
BEGIN
   DBMS_OUTPUT.put_line ('Constraint Name');
   OPEN cur_constraint;
   LOOP
      FETCH cur_constraint
      INTO tbl_name, constraint_nm;
      EXIT WHEN cur_constraint%NOTFOUND;
      DBMS_OUTPUT.put_line (constraint_nm||'~~'||tbl_name);
   END LOOP;
   close cur_constraint;
END CHECKS;
DECLARE
   tbl_name        VARCHAR2 (50);
   constraint_nm   VARCHAR2 (100);
   CURSOR cur_constraint
   IS
      SELECT DISTINCT table_name, constraint_name
        FROM all_constraints
       WHERE     constraint_type = 'R'
             AND STATUS = 'ENABLED'
             AND R_OWNER = 'owner1'
             AND r_constraint_name = 'constraint1';
BEGIN
   FOR i IN cur_constraint
   LOOP
      EXIT WHEN cur_constraint%NOTFOUND;
      DBMS_OUTPUT.put_line (i.constraint_name||' is in '||i.table_name);
   END LOOP;
END;
它按预期返回一行


请帮助我理解为什么当逻辑与我执行它的方式相同时,它的行为会很奇怪。

我想这是因为您的模式只能通过角色访问某些“owner1”模式对象,而不能直接授予。存储过程不考虑角色。有关更多详细信息,请参阅

正如Gary Myers所说,您可以将过程更改为:

CREATE OR REPLACE PROCEDURE schema_name.CHECKS
AUTHID CURRENT_USER
IS
...

然后,它将显示运行它的用户可以看到的约束。

所有约束都有点像镜子。根据授予该用户的授权,每个用户都会看到不同的内容。当作为DEFINE-RIGHTS存储过程执行时,它只显示过程所有者可以看到的内容,这是直接授予所有者(而不是通过角色)的特权的结果

当作为匿名块执行时,它将显示正在运行的用户直接或通过当前活动角色授予用户的权限所能看到的内容


调用程序权限存储过程(google AUTHID CURRENT_USER)将显示调用用户直接或通过当前活动角色授予用户后可以看到的内容。

我在名为“schema_name”的模式中编译此存储过程“owner1”仅存在于从“all_constraints”表获取数据的select查询中。如果我从“owner1”模式对象中选择数据,我觉得您的答案是有效的。或者我是否需要获得对“所有约束”表的“schema\u name”的select访问权限?到目前为止,“所有约束”具有“选择”访问“公共”的权限。这与您访问“所有约束”视图无关;这是因为ALL_CONSTRAINTS视图仅显示您有权访问的表上的约束。