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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With