Oracle Tips and Tricks — David Fitzjarrell

January 23, 2013

Privilege Is Everything, Sometimes

Filed under: General — dfitzjarrell @ 15:17

A common problem surfaced again in an Oracle forum I frequent — a user received a ‘table or view does not exist’ error when creating a procedure against a table he/she didn’t own. A straight select against the table succeeds from SQL*Plus so what is the problem?

It all boils down to privilege in this case. The user has grants on the table through a role, but no direct grants on that table have been made by the owner to the affected user. Since PL/SQL operates a bit differently than SQL*Plus direct grants are a necessity to create procedures and functions against tables and views a user does not own. Let’s look at an example:

SQL> create table location(
  2          yankpurt number,
  3          snozwert varchar2(12),
  4          hunlzap number);

Table created.

SQL>
SQL> begin
  2          for i in 1..100 loop
  3                  insert into location
  4                  values(i, 'SMAZOO!!!!', i);
  5          end loop;
  6
  7          commit;
  8
  9  end;
 10  /

PL/SQL procedure successfully completed.

SQL>
SQL> grant all on location to loc_role;

Grant succeeded.

SQL>
SQL> create public synonym location for bong.location;

Synonym created.

SQL>
SQL> connect bing/bong
Connected.
SQL> set echo on
SQL>
SQL> CREATE or replace PROCEDURE TESTPROC
  2  AS
  3  BEGIN
  4    DBMS_OUTPUT.PUT_LINE('testing');
  5    select count(*) from LOCATION;
  6  END;
  7  /

Warning: Procedure created with compilation errors.

SQL>
SQL> show errors
Errors for PROCEDURE TESTPROC:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/3      PL/SQL: SQL Statement ignored
5/24     PL/SQL: ORA-00942: table or view does not exist
SQL>
SQL>
SQL> connect bong/bing
Connected.
SQL>
SQL> grant all on location to bing;

Grant succeeded.

SQL>
SQL> connect bing/bong
Connected.
SQL> set echo on serveroutput on size 1000000
SQL>
SQL> CREATE or replace PROCEDURE TESTPROC
  2  AS
  3  BEGIN
  4    DBMS_OUTPUT.PUT_LINE('testing');
  5    select count(*) from LOCATION;
  6  END;
  7  /

Warning: Procedure created with compilation errors.

SQL>
SQL> show errors
Errors for PROCEDURE TESTPROC:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/3      PLS-00428: an INTO clause is expected in this SELECT statement
SQL>
SQL>
SQL> CREATE or replace PROCEDURE TESTPROC
  2  AS
  3    loc_ct number;
  4  BEGIN
  5    DBMS_OUTPUT.PUT_LINE('testing');
  6    select count(*) into loc_ct from LOCATION;
  7    dbms_output.put_line(loc_ct);
  8  END;
  9  /

Procedure created.

SQL>
SQL> exec testproc;
testing
100

PL/SQL procedure successfully completed.

SQL>

SQL>

Besides the user-inflicted error (PLS-00428: an INTO clause is expected in this SELECT statement) the main problem was the lack of direct grants against the table in question. Correcting that cleared up the “PL/SQL: ORA-00942: table or view does not exist” error; since PL/SQL cannot recognize grants through roles on objects a user doesn’t own the procedure creation failed even though a select through SQL*Plus succeeded. Without direct grants on an object a user cannot create procedures or functions against that object.

Privilege, sometimes, is everything.

Blog at WordPress.com.