Skip to content
Home » Oracle » How to Resolve ORA-01031: Insufficient Privileges

How to Resolve ORA-01031: Insufficient Privileges

ORA-01031

ORA-01031: Insufficient Privileges means that the current user did not use the right privilege to process the SQL statement.

Since this error can be seen almost in every kind of SQL statement, sometimes you would never know what privilege you lack. So I do my best to collect cases for you.

There're several error patterns of ORA-01031 in this post. You may click whichever situation you encountered.

  1. Select (Query)
  2. Create Table
  3. Create Index
  4. Create View
  5. Create Synonym
  6. Create Materialized View
  7. Insert, Update and Delete
  8. Alter Table (Add Constraint)
  9. Alter Table (Other's Table)
  10. Alter User
  11. Analyze Table
  12. Password Change
  13. EXECUTE IMMEDIATE
  14. DGMGRL
  15. Alter Pluggable Database Close
  16. PDB Clone
  17. GRANT System Privilege

Select (Query)

Tried to select other's table, we got ORA-01031: insufficient privileges.

SQL> show user
USER is "HR"
SQL> select distinct gender from oe.customers;
select distinct gender from oe.customers
                               *
ERROR at line 1:
ORA-01031: insufficient privileges

Theoretically, if we can't see other's table, we got ORA-00942: table or view does not exist. But the error message indicates us that we don't use the right privilege to do it. Why? We'd better do some tests.

The first test is that, can we describe the table's definition?

SQL> desc oe.customers;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
...
 GENDER                                             VARCHAR2(1)
...

Yes, we can see its metadata, but not data.

So what object privileges we have now? Let's check them by a privileged user.

SQL> show user
USER is "SYSTEM"
SQL> select privilege from dba_tab_privs where owner = 'OE' and table_name = 'CUSTOMERS' and grantee = 'HR' order by 1;

PRIVILEGE
----------------------------------------
DELETE
INSERT
UPDATE

OK, we can INSERT, UPDATE and DELETE, but no SELECT privilege. This is really weird.

Solution to ORA-01031

To solve insufficient privilege in querying, we should grant SELECT privilege to the user.

SQL> grant select on oe.customers to hr;

Grant succeeded.

Then we query the table again.

SQL> select distinct gender from oe.customers;

G
-
M
F

OK, the problem is solved.

Create Table

Let's see what will happen if the new user wants to create a table.

C:\Users\Administrator>sqlplus thomas/thomas@orcl
...
SQL> create table test1 (id number, e_id number);
create table test1 (id number, e_id number)
*
ERROR at line 1:
ORA-01031: insufficient privileges

Immediately, ORA-01031: insufficient privileges shows up, which tells the user who doesn't have the right privilege to do that.

Solution to ORA-01031

The solution is simple, just grant CREATE TABLE to user, a schema-based privilege or CREATE ANY TABLE, a system-wide privilege.

SQL> conn / as sysdba
Connected.
SQL> grant create table to thomas;

Grant succeeded.

Then tell him to try it again.

SQL> create table test1 (id number, e_id number);

Table created.

If you use EXECUTE IMMEDIATE to run CREATE TABLE in a stored procedure, you may check ORA-01031 in EXECUTE IMMEDIATE section in this post.

Create Index

In the above section, we have granted CREATE TABLE to the new user, which naturally enables it to CREATE INDEX in his own schema.

Please note that, CREATE INDEX is not a valid privilege, but CREATE ANY INDEX is.

Let's see an example and then we guess what privilege we need.

Suppose the new user wants to create an index for SH.CUSTOMERS in his own schema, so we grant SELECT on that table (object privilege) by instinct.

SQL> grant select on sh.customers to thomas;

Grant succeeded.

Then it tries to create an index on that table.

SQL> create index customer_id_gen_idx on sh.customers (cust_id, cust_gender);
create index oe.customer_id_gen_idx on sh.customers (cust_id, cust_gender)
                                          *
ERROR at line 1:
ORA-01031: insufficient privileges

Solution to ORA-01031

This is because SELECT on that table is not enough, you should additionally grant INDEX on that table to user, which is an object privilege.

SQL> grant index on sh.customers to thomas;

Grant succeeded.

Try again.

SQL> create index customer_id_gen_idx on sh.customers (cust_id, cust_gender);

Index created.

Even though the case is possible in reality, we seldom create index for other user's table in our schema.

Create View

If you have read the above section, then you have known that you have to grant CREATE VIEW to the user in order to solve ORA-01031.

SQL> grant create view to thomas;

Grant succeeded.

If the user still got ORA-01031 after granting CREATE VIEW to him, it must be a deeper problem. That's why this section is little longer.

Inherit Privilege from Role

Some privileges inherit from role do not work in some situation, especially when accessing intermediate kinds of object, like views or store procedures.

Here is a case that can reproduce the error.

We grant role RESOURCE to the user. Then we grant the system privilege SELECT ANY TABLE to the role RESOURCE.

SQL> grant resource to thomas;

Grant succeeded.

SQL> grant select any table to resource;

Grant succeeded.

So we can expect that the user inherits the system privilege from RESOURCE. That is, it can select any other's table.

Let's do the first test. Use it to select other user's table SH.SALE.

SQL> select count(*) from sh.sales;

  COUNT(*)
----------
    918843

Good, it acts as we expect, although the user has not any object privilege on SH.SALE.

Let's do the second test. We use it to create a view which is based on other user's table SH.SALE.

SQL> create view sh_sales_v as select * from sh.sales;
create view sh_sales_v as select * from sh.sales
                                           *
ERROR at line 1:
ORA-01031: insufficient privileges

What happened? the user has CREATE VIEW and inherit SELECT ANY TABLE from RESOURCE, it should have no problem.

The result implies that the role's privileges does not reach underlying objects through intermediate objects like views.

Solution to ORA-01031

The solution to this problem is to grant SELECT on the table to user directly.

First, grant the object privilege explicitly to resolve the problem.

SQL> grant select on sh.sales to thomas;

Grant succeeded.

Then tell Thomas to create view again.

SQL> create view sh_sales_v as select * from sh.sales;

View created.

Now, it's no problem.

Please notice that, if you create a synonym on SH.SALES, it will succeed whether the explicit object privilege is granted directly or not.

Create Synonym

Tried to create a private synonym, but it failed with ORA-01031.

SQL> show user
USER is "HR"
SQL> create synonym customers for oe.customers;
create synonym customers for oe.customers;
*
ERROR at line 1:
ORA-01031: insufficient privileges

To solve the problem, just simply grant CREATE SYNONYM to the user.

SQL> grant create synonym to hr;

Grant succeeded.

Then create it again.

SQL> create synonym customers for oe.customers;

Synonym created.

Problem solved.

Create Materialized View

We talk about the error in the following 2 different patterns.

On Our Own Table

Tried to create a materialized view on a table of our own, but it failed with ORA-01031.

SQL> show user
USER is "HR"
SQL> create materialized view happy_employees as select * from employees where salary > 10000;
create materialized view happy_employees as select * from employees where salary > 10000
                                                                                   *
ERROR at line 1:
ORA-01031: insufficient privileges

To solve the problem, just simply grant CREATE MATERIALIZED VIEW to the user.

SQL> grant create materialized view to hr;

Grant succeeded.

Then create it again.

SQL> create materialized view happy_employees as select * from employees where salary > 10000;

Materialized view created.

On Other's Table

To create a materialized view on other's table, we need not only CREATE MATERIALIZED VIEW, but also SELECT privilege on the table. Other object privilege, such as INSERT, UPDATE or DELETE is useless here.

SQL> show user
USER is "SYSTEM"
SQL> grant create materialized view to sh;

Grant succeeded.

SQL> grant select on hr.employees to sh;

Grant succeeded.

Now, we can create a materialized view on other's table.

SQL> show user
USER is "SH"
SQL> create materialized view happy_employees as select * from hr.employees where salary > 10000;

Materialized view created.

Insert, Update and Delete

You may have the right to select other's table.

SQL> conn sh/sh
Connected.
SQL> select * from hr.t1;

        ID
----------
         1
         2
         3

But you may not have the right to perform some Data Manipulation Language (DML) operations on the table. For example, INSERT INTO some data like this:

SQL> insert into hr.t1 values (4);
insert into hr.t1 values (4)
               *
ERROR at line 1:
ORA-01031: insufficient privileges

This is because you lack INSERT, UPDATE or DELETE privilege to modify on that table which is usually owned by others.

Solution to ORA-01031

Clearly, the right privilege is INSERT, UPDATE or DELETE at object-level. You may ask for DBA or the object owner to grant the privilege to you.

Grant DML

We may grant individual privileges to the user.

SQL> conn hr/hr
Connected.
SQL> grant insert,update,delete on hr.t1 to sh;

Grant succeeded.

As we can see, the grantor grants 3 object privileges INSERT, UPDATE and DELETE on the table to the grantee at a time.

Grant All

In some cases, you may consider to grant all possible object privileges to user, for example:

SQL> grant all on hr.t1 to sh;

Grant succeeded.

In the statement, ALL is a keyword which means all possible privileges on specified object. For a table, it naturally includes not only SELECT, but also INSERT, UPDATE and DELETE.

As a result, we can insert some rows.

SQL> conn sh/sh
Connected.
SQL> insert into hr.t1 values (4);

1 row created.

SQL> commit;

Commit complete.
SQL> select * from hr.t1;

        ID
----------
         1
         2
         3
         4

That is to say, not only SELECT, but also INSERT, UPDATE or DELETE privilege you should have to manipulate tables owned by other users.

Alter Table (ADD CONSTRAINT)

In the above section, we have granted CREATE TABLE to the user. Implicitly, he also has the right to ALTER TABLE on schema-level. So the cause of ORA-01031 in ALTER TABLE is not so obvious as we thought.

Please note that, ALTER TABLE is not a privilege, but ALTER ANY TABLE is. That's why there's no such GRANT ALTER TABLE TO statement.

Let's see an example. User Thomas wants to add a constraint so as to make a reference to another user's data, so we grant SELECT on that table to the user by instinct.

SQL> grant select on hr.employees to thomas;

Then we make the reference.

SQL> alter table test1 add constraint fk_eid foreign key (e_id) references hr.employees (employee_id);
alter table test1 add constraint fk_eid foreign key (e_id) references hr.employees (employee_id)
                                                                         *
ERROR at line 1:
ORA-01031: insufficient privileges

We got ORA-01031.

Solution to ORA-01031

The right privilege to reference other's data is not SELECT, it's REFERENCES.

We should grant REFERENCES on the table to user either by HR or privileged users.

SQL> grant references on hr.employees to thomas;

Grant succeeded.

Now Thomas can finish his job.

SQL> alter table test1 add constraint fk_eid foreign key (e_id) references hr.employees (employee_id);

Table altered.

Alter Table (Other's Table)

If you were trying to alter other user's table without a proper privilege, you may get ORA-01031 like this:

SQL> show user
USER is "HR"
SQL> alter table sh.customers add (col varchar2(10));
alter table sh.customers add (col varchar2(10))
*
ERROR at line 1:
ORA-01031: insufficient privileges

Although you have some other object privilege like SELECT or UPDATE on the table, you still cannot add a column for other user's table.

Solution

The right privilege to alter other's table is not UPDATE, it's ALTER. The single word, the single word can be an object privilege.

SQL> grant alter on sh.customers to hr;

Grant succeeded.

Then do it again.

SQL> alter table sh.customers add (col varchar2(10));

Table altered.

System privilege ALTER ANY TABLE shall also work, but it's unnecessary for most cases.

Alter User

Tried to add some quota on tablespace to itself, but it lacks of some privileges.

SQL> show user
USER is "HR"
SQL> alter user hr quota unlimited on users;
alter user hr quota unlimited on users
*
ERROR at line 1:
ORA-01031: insufficient privileges

Solution

The right privilege in this case is ALTER USER.

SQL> show user
USER is "SYSTEM"
SQL> grant alter user to hr;

Grant succeeded.

Then we do it again.

SQL> show user
USER is "HR"
SQL> alter user hr quota unlimited on users;

User altered.

SQL> alter user oe account lock;

User altered.

As you can see, with ALTER USER privilege, the user not only can grant some quota to itself, but also can change other's status.

Analyze Table

We saw ORA-01031 when we tried to analyze other user's table.

SQL> show user
USER is "HR"
SQL> analyze table sh.customers validate structure;
analyze table sh.customers validate structure
                 *
ERROR at line 1:
ORA-01031: insufficient privileges

Solution

To enable an user to analyze and gather statistics, the correct privilege is ANALYZE ANY.

SQL> show user
USER is "SYS"
SQL> grant analyze any to hr;

Grant succeeded.

Then analyze the table again.

SQL> analyze table sh.customers validate structure;

Table analyzed.

We solved it.

Password Change

Tried to change other's password by SQL*Plus command password, but the user has inadequate privileges.

SQL> show user
USER is "HR"
SQL> password oe
Changing password for oe
New password:
Retype new password:
ERROR:
ORA-01031: insufficient privileges


Password unchanged

Since password command is actually an ALTER USER statement, the correct privilege to change other's password is ALTER USER.

SQL> grant alter user to hr;

Grant succeeded.

Then do it again.

EXECUTE IMMEDIATE

Let's see how I reproduce ORA-01031 for statements using EXECUTE IMMEDIATE by the following example.

Inherit Privilege from Role

In the above section, I have granted role RESOURCE to THOMAS. Now I grant CREATE ANY DIRECTORY and DROP ANY DIRECTORY to the role RESOURCE.

SQL> grant create any directory, drop any directory to resource;

Grant succeeded.

So we can expect that the user can also do such operations by inheriting all privileges from RESOURCE.

Things look fine when we use the user to create or drop directories.

SQL> create directory tmp_path as '/u02/tmp';

Directory created.

SQL> drop directory tmp_path;

Directory dropped.

SQL> create directory tmp_path as '/u02/tmp';

Directory created

Now, Thomas would like to create directories in stored procedures which is also called named PL/SQL blocks or programming units.

First of all, DBA have to grant CREATE PROCEDURE to him before Thomas doing anything.

SQL> grant create procedure to thomas;

Grant succeeded.

Then Thomas create a procedure like this:

SQL> create or replace procedure drop_create_tmp_dir is
begin
execute immediate 'drop directory tmp_path';
execute immediate 'create or replace directory tmp_path as ''/u02/tmp''';
end drop_create_tmp_dir;
/
  2    3    4    5    6
Procedure created.

It seems no problem. But when we execute the stored procedure (named PL/SQL), we got ORA-01031 at line 3.

SQL> exec drop_create_tmp_dir;
BEGIN drop_create_tmp_dir; END;

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

Rationale

This is because the system privileges inherit from role cannot be used in named stored procedures with definer's right.

Solutions to ORA-01031

Now we have several options, the first one is to grant all necessary privilege to the user directly, the second one is to use invoker's right, and the last one is to use anonymous PL/SQL blocks.

1. Directly Granting to User

The user should directly get the system privilege from DBA, not inherit from role.

SQL> grant create any directory, drop any directory to thomas;

Grant succeeded.

Back to THOMAS, we can execute it again.

SQL> exec drop_create_tmp_dir;

PL/SQL procedure successfully completed.

The better thing is that we don't have to recompile the procedure.

2. Use Invoker's Right

Another way to solve ORA-01031 for statements in EXECUTE IMMEDIATE is to use invoker's right to define the procedure.

Let's revert the granting by SYS.

SQL> revoke create any directory, drop any directory from thomas;

Revoke succeeded.

Then we created the procedure with AUTHID CURRENT_USER clause.

SQL> create or replace procedure drop_create_tmp_dir authid current_user is
begin
execute immediate 'drop directory tmp_path';
execute immediate 'create or replace directory tmp_path as ''/u02/tmp''';
end drop_create_tmp_dir;
/
  2    3    4    5    6
Procedure created.

Try to execute the procedure by the user.

SQL> exec drop_create_tmp_dir;

PL/SQL procedure successfully completed.

By invoker's right, we can use role's privileges.

3. Anonymous PL/SQL Block

What we mean in the above is that role privileges cannot penetrate NAMED stored procedures. That is to say, you can use role privileges in anonymous PL/SQL blocks. For instance, we can rewrite the stored procedure to an anonymous PL/SQL as this:

begin
execute immediate 'drop directory tmp_path';
execute immediate 'create or replace directory tmp_path as ''/u02/tmp''';
end;
/

You can save and use it as a normal SQL script file.

For the same reason, CREATE TABLE in EXECUTE IMMEDIATE can also throw ORA-01031.

DGMGRL

DGMGRL allows user to query the status of all nodes involved through the local authentication without problem, but it might fail to switchover to a standby database or convert to a snapshot standby.

DGMGRL Switchover

Let's see a switchover in 11g, it will fail when you connect DGMGRL with local authentication.

[oracle@primary01 ~]$ dgmgrl /
...
DGMGRL> switchover to standb
Performing switchover NOW, please wait...
Operation requires shutdown of instance "primdb2" on database "primdb"
Shutting down instance "primdb2"...
ORA-01031: insufficient privileges

Warning: You are no longer connected to ORACLE.

Please complete the following steps and reissue the SWITCHOVER command:
        shut down instance "primdb2" of database "primdb"

DGMGRL>

But if you connect DGMGRL with the database password, the switchover will succeed.

[oracle@primary01 ~]$ dgmgrl sys/password@primdb1
...
DGMGRL> switchover to standb
Performing switchover NOW, please wait...
Operation requires shutdown of instance "primdb2" on database "primdb"
Shutting down instance "primdb2"...
Database closed.
Database dismounted.
ORACLE instance shut down.
New primary database "standb" is opening...
Operation requires shutdown of instance "primdb1" on database "primdb"
Shutting down instance "primdb1"...
ORA-01109: database not open

Database dismounted.
ORACLE instance shut down.
Operation requires startup of instance "primdb1" on database "primdb"
Starting instance "primdb1"...
ORACLE instance started.
Database mounted.
Switchover succeeded, new primary is "standb"
DGMGRL>

DGMGRL Convert

Same error happened in a conversion.

[oracle@primary01 ~]$ dgmgrl /
...
DGMGRL> CONVERT DATABASE standb TO SNAPSHOT STANDBY;
Converting database "standb" to a Snapshot Standby database, please wait...
Operation requires shutdown of instance "standb2" on database "standb"
Shutting down instance "standb2"...
ORA-01031: insufficient privileges

Warning: You are no longer connected to ORACLE.

Please complete the following steps and reissue the CONVERT command:
        shut down instance "standb2" of database "standb"

Solution to ORA-01031

You must use the database authentication to convert a standby database.

[oracle@primary01 ~]$ dgmgrl sys/password@primdb1
...
DGMGRL> CONVERT DATABASE standb TO SNAPSHOT STANDBY;
Converting database "standb" to a Snapshot Standby database, please wait...
Operation requires shutdown of instance "standb2" on database "standb"
Shutting down instance "standb2"...
ORA-01109: database not open

Database dismounted.
ORACLE instance shut down.
Continuing to convert database "standb" ...
Database "standb" converted successfully
...

For the same reason, the broker is unable to startup the new standby database during a switchover and throws ORA-01017 due to OS authentication.

Alter Pluggable Database Close

We saw an error when we tried to close a pluggable database (PDB) by a normal user.

SQL> conn hr/password@orclpdb
Connected.
SQL> show user
USER is "HR"
SQL> alter pluggable database close;
alter pluggable database close
*
ERROR at line 1:
ORA-01031: insufficient privileges

To solve ORA-01031, we take two steps to make the user be able to close a PDB.

1. Grant SYSDBA to the User

Please make sure that you login as SYS and are in the right container.

SQL> show user
USER is "SYS"
SQL> show con_namev
CON_NAME
------------------------------
ORCLPDB

Then we grant SYSDBA privilege to the user.

SQL> grant sysdba to hr;

Grant succeeded.

2. Connect as SYSDBA

The user should use SYSDBA privilege to connect to the PDB.

SQL> conn hr/password@orclpdb as sysdba
Connected.
SQL> alter pluggable database close;

Pluggable database altered.

Actually, the normal user has become a SYS which of course has the ability to maintain database.

PDB Clone

When you try to clone a remote PDB via a database link, you may see ORA-17628 and ORA-01031 at that moment. I have talk about it in that post.

GRANT System Privilege

It failed with ORA-01031 when we tried to grant a system privilege to another user.

SQL> show user
USER is "HR"
SQL> grant create table to oe;
grant create table to oe
*
ERROR at line 1:
ORA-01031: insufficient privileges

To be able to grant any system privilege to any grantee, the grantor requires GRANT ANY PRIVILEGE privilege.

SQL> show user
USER is "SYSTEM"
SQL> grant grant any privilege to hr;

Grant succeeded.

That is to say, the insufficient privilege in this case is GRANT ANY PRIVILEGE.

1 thought on “How to Resolve ORA-01031: Insufficient Privileges”

  1. Mauricio Rojas Villarreal

    Hola! Justamente estábamos tratando de implementar una autogestión para poder crear usuarios y la parte de la cláusula de autenticación nos vino perfecto. Infinitas gracias por compartir este conocimiento valioso

Leave a Reply

Your email address will not be published. Required fields are marked *