select object_name from user_objects where object_type='PROCEDURE';Information about procedures stored by the Oracle also includes references to all objects the procedures reference. Oracle needs that information because the procedures depend on these objects. As probably you remember we got compiling errors when referenced inside a procedure a table that didn't exist. Thus, Oracle wants to keep all these information in case that the reference objects will be changed after a procedure is successfully compiled. For example, our stored procedure ShowTestTable
create or replace procedure ShowTestTable as
begin
for v_row in (select name, id from pl_test) loop
dbms_output.put_line('name: ' || v_row.name || ' id: ' || v_row.id);
end loop;
end;
uses table pl_test. Once the procedure successfully created we can take a look at its status:
SQL> select object_name, status 2 from user_objects 3 where object_type='PROCEDURE' or object_type='FUNCTION'; OBJECT_NAME STATUS -------------------------- ADDUSER VALID ADD_TEST_VALUE VALID GET_SUM VALID INSERT_IN_TEST VALID PRINTREQUIRED VALID SHOWTESTTABLE VALIDNow we will modify the table pl_test.
SQL> alter table pl_test add phone number(7); Table altered.Now, when the table got changed what happened to the stored procedure that depends on that table?
SQL> select object_name, status 2 from user_objects 3 where object_type='PROCEDURE' or object_type='FUNCTION'; OBJECT_NAME STATUS -------------------------- ADDUSER VALID ADD_TEST_VALUE VALID GET_SUM VALID INSERT_IN_TEST VALID PRINTREQUIRED VALID SHOWTESTTABLE INVALIDAs we can see the procedure is marked as INVALID. If an object is invalidated, the PL/SQL engine will automatically try to recompile it the next time it is called. Since all we did was just adding a new column to the table and our procedure doesn't use that column, Oracle will recompile it with no errors. Thus, after
SQL> exec ShowTestTable;this procedure will be VALID again.
The kind of the dependency we just discussed is called direct dependency. Oracle also takes care of indirect dependencies, when a procedure doesn't directly refer to a changed object, but it refers to another object which becomes invalid upon those changes. We can illustrate this kind of dependency by creating another procedure that doesn't do anything to the pl_test table directly, but calls the ShowTestTable function.
The situations with packages is different, however. This difference is caused by the fact that a package consists of two parts the header and the body. The body of a package depends on the header, but the header does not depend on the body. All outside procedures that call procedures from this package depend only on the header. Thus, if a package body becomes invalid, it doesn't influence the header or outside procedures. This situation is very well illustrated by the example from Scott Urman book.
Case 1: In the first case we'll assume that UserA owns all the objects listed above, and the UserB was only granted the execute privilege on the RecordFullClass
SQL> grant execute on RecordFullClass to UserB;

Case 2:
The second case is very similar to the first one, except this time we assume that UserB also has a table
temp_table.

Case 3: In the last case we assume that UserB owns the RecordFullClass procedure. Of course, in this case this procedure needs to be a little bit different. We need to manually specify that it should read from the table classes from the UseA schema and should call the function AlmostFull that belongs to the UserA:
create or replace procedure RecordFullClass as
cursor c_Classes is select department, course from UserA.classes;
begin
for c_ClassRec in c_Classes loop
if UserA.AlmostFull(v_ClassRec.department, v_ClassRec) then
insert into temp_table (char_col)
values (v_ClassRec.department||' '||v_ClassRec||' is almost full');
end if;
end loop;
end RecordFullClass;
Since now the RecordFullClass dosn't belong to the schema UserA, UserB needs privileges to execute
the AlmostFull function and select from the classes table.
SQL> grant execute on AlmostFull to UserB; SQL> grant select on classes to UserB;

There is one more thing we would like to point out.
![]() |
If a subprogram needs some privileges these privileges must be granted explicitly and not through a role.
|
This default behavior can be changed (starting from Oracle8i). In an invoker's rights subprogram, external references are resolved under the privilege set of the caller, not the owner. An invoker's rights routine is created by using authid clause. It is valid for stand-alone subprograms, package specifications, and object type specifications only. The general syntax of using this clause is
create [or replace] function function_name [(parameter_list)] return return_type
[authid {current user | definer}]
{as | is}
function_body;
create [or replace] function procedure_name [(parameter_list)]
[authid {current user | definer}]
{as | is}
procedure_body;
create or replace package package_name
[authid {current user | definer}]
{as | is}
package_specification;
If the current user option is specified in the authid clause, the object will have invoker's
rights. If definer is specified or the authid clause is not present, then the object will
have the definer's right. Please see Scot Urman's example for more details.
| Level | Meaning | Description |
| WNDS | Writes No Database Set | The function does not modify any database tables (using DML statements) |
| RNDS | Reads No Database Set | The function does not read any database table (using select statement) |
| WNPS | Writes No Package Set | The function does not modify any packaged variables (no package variables are used on the left side of an assignment or in a fetch statement) |
| RNPS | Reads No Package State | The function does not examine any packaged variables (no package variables appear on the right side of an assignment operator or as a part of a procedural or SQL expression) |
Depending of the purity level of a function, it is subject to the following restrictions:
In addition to these restrictions, a user-defined functions must also meet the following requirements to be callable from a SQL statement:
Here is an example of a function that can be used in a SQL statement
create or replace function Balance(end_date in date) return number as
res BankAccount.amount%type;
begin
select sum(amount)
into res
from BankAccount
where tdate <= end_date;
return res;
end Balance;
In class assignment: