Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stored procedure not returning correct result

I have a stored procedure like this

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;

And I execute this procedure by

set serveroutput on

BEGIN
   schema_name.CHECKS ();
END;

And the output I get is

Procedure created.
Constraint Name
PL/SQL procedure successfully completed.

It's not returning any result but ideally it should be returning a row (the select query used to define the cursor will return a row).

When I execute the above code as a PL/SQL Block like this

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;

It is returning one row as expected.

Please help me understand why it is behaving strange when the logic is same except the way I execute it.

like image 285
Vivek Avatar asked Jul 26 '11 16:07

Vivek


People also ask

Can a stored procedure return a result set?

In addition to returning output parameters, a stored procedure can return a result set (that is, a result table associated with a cursor opened in the stored procedure) to the application that issues the CALL statement. The application can then issue fetch requests to read the rows of the result set cursor.

Does a stored procedure need to return a value?

Return Value in SQL Server Stored Procedure In default, when we execute a stored procedure in SQL Server, it returns an integer value and this value indicates the execution status of the stored procedure. The 0 value indicates, the procedure is completed successfully and the non-zero values indicate an error.

What is wrong with stored procedures?

Stored procedures are difficult to unit test. With an ORM, you can mock your database code so as to be able to test your business logic quickly. With stored procedures, you have to rebuild an entire test database from scratch. Stored procedures offer no performance advantage whatsoever.

Can stored procedure return multiple result sets?

Most stored procedures return multiple result sets. Such a stored procedure usually includes one or more select statements. The consumer needs to consider this inclusion to handle all the result sets.

Can you return data from a stored procedure?

Returning Data Using a Return Code. Stored Procedures should always indicate failure with an error (generated with THROW/RAISERROR if necessary), and not rely on a return code to indicate the failure. Also you should avoid using the return code to return application data.

How do I return a value from a procedure?

A procedure can return an integer value called a return code to indicate the execution status of a procedure. You specify the return code for a procedure using the RETURN statement. As with OUTPUT parameters, you must save the return code in a variable when the procedure is executed in order to use the return code value in the calling program.

What should I do if a stored procedure fails?

Stored Procedures should always indicate failure with an error (generated with THROW/RAISERROR if necessary), and not rely on a return code to indicate the failure. Also you should avoid using the return code to return application data.

What happens if multiple select statements are run during a procedure?

If multiple such SELECT statements are run during the execution of the stored procedure, multiple result sets will be sent to the client. This behavior also applies to nested TSQL batches, nested stored procedures and top-level TSQL batches. Examples of Returning Data Using a Result Set


2 Answers

I imagine this is because your schema has access to some 'owner1' schema objects only via a role and not granted directly. Roles are not taken into account by stored procedures. See this AskTom thread for more details.

As Gary Myers says, you can change the procedure to:

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

and it will then show constraints that the user running it can see.

like image 83
Tony Andrews Avatar answered Nov 02 '22 00:11

Tony Andrews


ALL_CONSTRAINTS is a bit like a mirror. Every user will see something different in there based on grants to that user. When executed as a DEFINE RIGHTS stored procedure it shows only what the owner of the procedure can see as a result of privileges granted directly to the owner (not through a role).

When executed as an anonymous block, it will show what the running user can see as a result of privileges granted to the user directly OR through a currently active role.

An invoker rights stored procedure (google AUTHID CURRENT_USER) will show what the invoking user can see as a result of grants to the user directly or through a currently active role.

like image 29
Gary Myers Avatar answered Nov 02 '22 01:11

Gary Myers