|Author's name: Norman Dunbar;
Author's Email: Oracle@bountifulsolutions.co.uk
|Date written: 04/07/2001
Oracle version(s): 7.3.4 onwards
|Procedures and scripts that run perfectly within SQL*Plus fail with permissions errors, or don't compile under PL/SQL. Why is this ?|
Back to index of questions
The quick and dirty answer is - it is all down to roles. When any PL/SQL procedure, function whether stand alone or part of a package is run, it disables all roles. When your role is disabled, all privileges that it had are gone as well and you can no longer access the object in question. Oracle states that 'roles were created to facilitate user maintenance'
How to test for the possible appearance of this problem is reasonably simple. In an SQL*Plus session enter the following command :
set role none;
From now on, any SQL commands you execute will be run in an identical manner to what will happen under PL/SQL. To solve the problem, you need to grant the appropriate privileges directly to the user and not through a role. Even the SYSTEM user suffers from this problem as the following example shows (assumes connected as SYSTEM user):
Select table_name from all_tables where owner = 'OTHER_USER';
This works in SQL*Plus, and produces the expected results - a list of all tables owned by other_user. Now create a small procedure to carry out a similar task under PL/SQL.
create or replace procedure Test (iUserName in varchar2) is BEGIN dbms_output.enable(100000); for TableList in (select table_name from sys.all_tables where owner = upper(iUserName)) loop dbms_output.put_line(TableList.table_name); end loop; END; /
The first problem is simply that you will get an error, PLS_00201 sys.all_tables must be declared. This is because the compiler is checking the privileges that you as a 'no-role' user have to access sys.all_tables. You don't have any, so you cannot even compile the procedure. If you get granted select any table You will be able to compile the procedure. Once compiled and error free, revoke the select any table privilege from system, and execute it as follows :
set serverout on execute test('OTHER_USER');
All you get in return is a message to say 'PL/SQL procedure successfully completed'. You might be lucky, and get a few table names listed - these are tables which your user has been explicitly granted select privileges on.
If you now again, as SYS, grant select any table to system;, you will be able to run the procedure again, and this time, the results will be as expected.
Seems to be a difficult subject this. There is no mention in the PL/SQL User Guide and Reference about this problem. There is note 27287.1 on metalink though and this can be found by searching for PLS-00201. As ever, MetaLink needs a logon.
Back to top
Back to index of questions