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

Viv*_*vek 6 oracle plsql stored-procedures

我有这样的存储过程

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;
Run Code Online (Sandbox Code Playgroud)

我执行此过程

set serveroutput on

BEGIN
   schema_name.CHECKS ();
END;
Run Code Online (Sandbox Code Playgroud)

我得到的输出是

Procedure created.
Constraint Name
PL/SQL procedure successfully completed.
Run Code Online (Sandbox Code Playgroud)

它没有返回任何结果,但理想情况下它应该返回一行(用于定义游标的select查询将返回一行).

当我像这样执行上面的代码作为PL/SQL块时

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;
Run Code Online (Sandbox Code Playgroud)

它按预期返回一行.

请帮助我理解为什么当逻辑相同时它会表现得很奇怪,除了我执行它的方式.

Ton*_*ews 8

我想这是因为您的架构只能通过角色访问某些"owner1"架构对象,而不是直接授予.存储过程不会考虑角色.有关详细信息,请参阅此AskTom线程.

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

CREATE OR REPLACE PROCEDURE schema_name.CHECKS
AUTHID CURRENT_USER
IS
...
Run Code Online (Sandbox Code Playgroud)

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


Gar*_*ers 3

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

当作为匿名块执行时,它将显示运行用户可以看到的内容,这是直接授予用户或通过当前活动角色授予权限的结果。

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