0

Running EXECUTE IMMEDIATE for CREATE PROCEDURE statement, from an anonymous PL/SQL block is working as expected. But if I have the same query inside a standalone procedure and call that procedure from the PL/SQL block it gives me the following error:

ORA-01031: insufficient privilege

Example:

connect sys/<sys_pass>@<tns_alias> as sysdba;
alter session set "_oracle_script"=true;

-- not relevant, just for dropping the user
-- https://stackoverflow.com/a/50711859/10721332
CREATE OR REPLACE PROCEDURE drop_user
  ( user_name IN varchar2 )
IS
  v_user_exists NUMBER;
BEGIN
  LOOP
    FOR c IN (SELECT s.sid, s.serial# FROM v$session s WHERE upper(s.username) = user_name)
    LOOP
      EXECUTE IMMEDIATE
        'alter system kill session ''' || c.sid || ',' || c.serial# || ''' IMMEDIATE';
    END LOOP;
    BEGIN
      EXECUTE IMMEDIATE 'drop user ' || user_name || ' cascade';
      EXCEPTION WHEN OTHERS THEN
      IF (SQLCODE = -1940) THEN
        NULL;
      ELSE
        RAISE;
      END IF;
    END;
    BEGIN
      SELECT COUNT(*) INTO v_user_exists FROM dba_users WHERE username = user_name;
      EXIT WHEN v_user_exists = 0;
    END;
  END LOOP;
END;
/

call drop_user('CREED');
create user creed identified by bratton;
grant connect, resource to creed;
grant unlimited tablespace to creed;

connect creed/bratton@<tns_alias>;
set serveroutput on;

---------------------------------------------------

CREATE OR REPLACE PROCEDURE executor(
  query VARCHAR2
) IS
BEGIN
    EXECUTE IMMEDIATE query;
EXCEPTION
    WHEN OTHERS THEN dbms_output.put_line(sqlerrm || ' : ' || query);
END;
/

DECLARE
    query1 varchar2(200);
    query2 varchar2(200);
BEGIN
    query1 := 'create or replace procedure PROC1 is begin dbms_output.put_line(''hello world''); end;';
    executor(query1);          -- doesn't work
    query2 := 'create or replace procedure PROC2 is begin dbms_output.put_line(''hello world''); end;';
    EXECUTE IMMEDIATE query2;  -- works
END;
/

Why does query2 work correctly while query1 fails to execute?

I tried the following, which gave me the same error:

  1. Altering the CURRENT_SCHEMA inside the procedure
  2. Adding the SCHEMA prefix in the procedure name
  • 1
    Because the privilege you are trying to use within the stored procedure is granted to you via a role, not directly. You can [read about invoker's rights and definer's rights](https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/plsql-subprograms.html#GUID-41D23DE7-3C07-41CF-962B-F92B696594B5). The code you posted doesn't match your question title; but why would you want to create a procedure dynamically? – Alex Poole Apr 27 '23 at 07:48

1 Answers1

0

It seems that you got privileges via role; did you? If so, then it works as expected because such a privileges will work at SQL level or anonymous PL/SQL blocks, but won't work in named procedures (that would be stored procedures, functions, packages, triggers).

What to do? Grant privileges directly, not via role.

Littlefoot
  • 131,892
  • 15
  • 35
  • 57