Skip to Main Content
  • Questions
  • Strange behaviour with excecute immediate.

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Ingimundur.

Asked: November 12, 2018 - 4:13 pm UTC

Last updated: May 26, 2025 - 7:31 am UTC

Version: Oracle 11.2.0.4.0

Viewed 1000+ times

You Asked

Hi,

Had problems with SQLLive, (500 response), therefore the examples are her.

I have a strange behaviour with execute immediate, where it behaves differently from within a PL/SQL procedure than it does when running it standalone.

Here is the example:
I create a simple table
CREATE TABLE TEST01 
(
  ID NUMBER 
, TEXT VARCHAR2(100 CHAR) 
);


Then I create a very simple procedure that will create a table based on the original table
CREATE OR REPLACE PROCEDURE test02 AS
    
BEGIN
    EXECUTE IMMEDIATE 'create table ABCD as select * from TEST01' ;
    COMMIT ;
   
END test02;


When I run this:
begin
    test02();
end;


I receive the following error:
ORA-01031: insufficient privileges
ORA-06512: at "INGIMUNDUR.TEST02", line 4
ORA-06512: at line 2
01031. 00000 - "insufficient privileges"

But if I run:
BEGIN
    EXECUTE IMMEDIATE 'create table ABCD as select * from TEST01' ;
    COMMIT ;
   
END;


everything runs fine, with no errors.

Why is this discrepancy?

Regards,
Ingimundur K. Gudmundsson.

p.s. I also tested this on an Oracle XE 11g, and the behaviour is the same.

and Chris said...

That's because you need to grant "create table" to your user. Not inherit it via a role:

CREATE TABLE TEST01 (
  ID NUMBER 
, TEXT VARCHAR2(100 CHAR) 
);

CREATE OR REPLACE PROCEDURE test02 AS   
BEGIN
    EXECUTE IMMEDIATE 'create table ABCD as select * from TEST01' ;
    COMMIT ;
   
END test02;
/

exec test02();

ORA-01031: insufficient privileges

grant create table to chris;

exec test02();

desc ABCD;

Name   Null?   Type                 
ID             NUMBER               
TEXT           VARCHAR2(100 CHAR)   


You don't need this when running anonymous blocks. Only compiled PL/SQL.

Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thanks!!

Ingimundur Gudmundsson, November 13, 2018 - 2:01 pm UTC

Thanks Chris for the very quick reply. Oddly I did not know there was a difference in privileges like that, especially when one runs it as the same user. But it sounds logical though.

Regards
Ingimundur

A working alternative

Jiri Suchy, May 22, 2025 - 5:25 am UTC

Hi,
Thanks for the explanation. I encountered the same problem before reading this thread, and another approach worked for me — using AUTHID CURRENT_USER:
SQL> CREATE TABLE TEST01 (
  2    ID NUMBER
  3  , TEXT VARCHAR2(100 CHAR)
  4  );

Table created.

SQL> CREATE OR REPLACE PROCEDURE test02 AS
  2  BEGIN
  3      EXECUTE IMMEDIATE 'create table ABCD as select * from TEST01' ;
  4      COMMIT ;
  5  END test02;
  6  /

Procedure created.

SQL> exec test02();
BEGIN test02(); END;

*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "LADB_JS.TEST02", line 3
ORA-06512: at line 1


SQL> CREATE OR REPLACE PROCEDURE test02 AUTHID CURRENT_USER AS
  2  BEGIN
  3      EXECUTE IMMEDIATE 'create table ABCD as select * from TEST01' ;
  4      COMMIT ;
  5  END test02;
  6  /

Procedure created.

SQL> exec test02();

PL/SQL procedure successfully completed.

SQL> desc ABCD
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER
 TEXT                                               VARCHAR2(100 CHAR)

Regards
Jiri
Connor McDonald
May 23, 2025 - 8:04 am UTC

When using AUTHID CURRENT_USER , you re-gain access to the privs you have via a role.

Jiri Suchy, May 23, 2025 - 9:58 am UTC

Thanks for your reply. I think I understand your explanation, but I'm not sure about the consequences. Which approach is better — granting CREATE TABLE, or using AUTHID CURRENT_USER?
Regards
Jiri
Chris Saxon
May 23, 2025 - 12:35 pm UTC

With AUTHID CURRENT_USER, whoever calls the procedure needs CREATE TABLE privileges, either directly or via a role.

This means the user calling the code can also run CREATE TABLE any time - generally something undesirable.

If you grant the code owner CREATE TABLE, then users calling it can only create tables via the API. They can't make tables any other way. This is generally preferable.

There is another option - code-based access control. With this you grant roles to procedures. So the privileges are only active while calling that specific code unit.

Rich and I discussed the ins and outs of these in an Office Hours earlier this year:


Jiří Suchý, May 25, 2025 - 2:32 pm UTC

Thanks for your explanation.
Regards
Jiri
Connor McDonald
May 26, 2025 - 7:31 am UTC

Glad to help

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library