Link to home
Start Free TrialLog in
Avatar of seazodiac
seazodiacFlag for United States of America

asked on

ORA-01031: insufficient privileges when try to alter index in the stored procedure.


I have grappled with this nasty "NO-NO" for quite a while, just cannot seem to get it to work. My goal is simple, try to rebuild the index in a procedure, which requires me to embed the "ALTER INDEX" inside the dynamic SQL.

Basic info here: oracle9i database, LINUX AS 2.1 (i don't think it matters though).

What I have tried:
Log in as the SCHEMA OWNER.

1. I have tested by calling "alter index <index_name> rebuild online compute statistics" in the sqlplus window , it worked fine.
2. the roles and sys privs this accout have are:
ROLE: DBA, CONNECT, RESOURCE.
SYSTEM PRIVS: create any index, alter any index, create any indextype, alter any indextype.
3. Then everytime, I execute the "exec cmdb_util.rebuild_all_indexes" . it threw me off with the ORA-01031.

Don't explain to me that ROLE is disabled in the stored procedure because I have all index related system privileges directly assigned.

Anyone, please chime in.....


---------My code is below, it's pretty simple, you can test by just copying and pasting.
CREATE OR REPLACE PACKAGE cmdb_util
AS
TYPE g_ind_cursor_type IS REF CURSOR;
PROCEDURE rebuild_all_indexes;
END;
/


PROCEDURE rebuild_all_indexes
AS

l_ind_name VARCHAR2(30);
g_ind_cursor g_ind_cursor_type;
BEGIN
      OPEN g_ind_cursor FOR 'select index_name FROM user_indexes where index_name NOT LIKE '||chr(39)||'SYS_%'||chr(39);
      FETCH g_ind_cursor INTO l_ind_name;
      LOOP
            EXIT WHEN g_ind_cursor%NOTFOUND;      
            execute immediate 'ALTER INDEX '||l_ind_name||' REBUILD ONLINE COMPUTE STATISTICS';            
            FETCH g_ind_cursor INTO l_ind_name;
      END LOOP;
      CLOSE g_ind_cursor;
      
END;

END cmdb_util;
/
Avatar of dsacker
dsacker
Flag of United States of America image

You've got a good one ... here are a few admitted quirks which may or may not work for you ... not directly related to alter index, but something not unlike this happened to me on creating tables within a procedure:

*  Did you by chance have the 10032 event set? Yeah, I know ... sounds far-fetched ... but turning off the trace event sometimes helps.

*  If it works from an anonymous PL block, but not from a procedure, disconnect and reconnect, then try it again.  I'm sure you've done this, but am just going over a few "features" that have scratched the itch.

Just chiming in. :)
Avatar of Kong
Kong

Why not trap the exception and print out the index it is failing on and then try rebuilding that from your SQL*Plus login?

ie:

PROCEDURE
CURSOR c IS
   SELECT 'alter index ' || index_name || ' rebuild online ...' s
      FROM user_indexes
   WHERE ...;

stm VARCHAR2(2000);
BEGIN
   FOR r IN c
   LOOP
      stm := r.s;
      execute immediate stm;
   END LOOP;
EXCEPTION
   WHEN OTHERS THEN
      dbms_output.put_line('ERROR ...');
      dbms_output.put_line(stm);
END;

Just out of interest, why are you rebuilding all indexes? One would usually query index_stats table and build on an as required basis. You're putting your hand up for needless overhead & most likely inconsistent performance.

How many times have we heard: "This is taking a long time to run now and we haven't touched it...."

Just a bit of DBA gripe heh :-)

Good luck!

K
Which user was the procedure created using?  If created under a different user to the one you are trying to run on, you will be accessing with the default definer rights access model, perhaps you would want to change this to invoker rights?  

PROCEDURE rebuild_all_indexes
AUTHID CURRENT_USER
AS
This might seem odd, but try

grant create any table to user;

As a side note  you could simply have the procedure

PROCEDURE rebuild_all_indexes  
AS
BEGIN
  for C_ind in (select index_name from user_indexes
                        where index_name NOT LIKE 'SYS_%' ) LOOP

      execute immediate 'ALTER INDEX '||C_Ind.Index_Name ||
                                  ' REBUILD ONLINE COMPUTE STATISTICS';
  END LOOP;
     
END;

how may roles is the account in?
what's the default role for the account using for alter index?
did you use any proxy?
Avatar of seazodiac

ASKER

Sorry, I just got into my office ...

dsacker --->try both, but neither helped :-(
Kong ---> Believed, I have turned over every stoned I could spot, when I try to trapped which index(es) I bumped over, the results: None of them let me pass through. another fact is that the user account owns the tables as well as all indexes.

grim_toaster --->read my comment to Kong, then you know definer vs. invoker does not play a role here.

Bigfam5 --->Yes, I could do that (I will try that for sanity check and see if I could get around by that way). However, I would prefer to put all my procedures in one package since I have many more of them .

Danielzt: No, I am not using proxy , I directly log into the sqlplus window. if that's what you mean.


Any other ideas?

SOLUTION
Avatar of dsacker
dsacker
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The double semi-colons aren't by accident, as I'm sure you're aware. :)
Correction:  ||index|| should be ||index_name||
dsacker:
thanks for the effort. It's my bad. I should point it out in the very beginning, that I need this to be done in stored procedure.
I used this script for the past.
I suspected you did need it that way, as I sometimes need a stored procedure for things, too ... just wondered if it wasn't something beyond the 1031 error that perhaps would reveal itself in SQLPLUS, ie at the very table that could be the culprit or something like that.  Or did it execute flawlessly in your sqlplus .sql script in the past?
the script that alter all the indexes (the syntax are exactly the same as it appears in pl/sql) are working just fine .
Another possibility, then I'm out of ideas :)

Could the stored procedure actually put an index in use while trying to rebuild it?  See some interesting comments at:

     http://www.dbazine.com/weeg16.shtml





seazodiac,

Did you try to assign the system privilege  CREATE ANY TABLE


Yes.  i think I mention this account I used to run this rebuild index procedure is the schema owner.
Hmmm maybe I missed something but did you grant create index explicitly to the user or was it inherited from a role. Try granting create index explicitly...

Can't figure out why else it wouldn't work good luck!
Either grant explicitly the create index priv or run the procedure as invoker's rights:

procedure ...
authid current_user
IS
...

Roles are disabled in a definer rights (default) procedure
but they remain enabled in a invoker rights procedure.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Maybe you're missing the "unlimited tablespace" privilege?
Any luck? I'd be interested to hear how you went...

Yoren, "unlimited tablespace" is tagged onto the RESOURCE role.
Kong - I suggested it because roles don't take effect in stored procedures.
True, but then we're going down the definer vs invoker's rights path which seazodiac doesn't agree with...
something really strange is going on here....

I think I exhaust almost all the means, but seems going no where...
I will give one last shot tomorrow, report back....
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
HI All:
I finally got it over with, but I took Kong's list of sys privs , just assigned them to the user account, and it worked. I am still puzzling what exaclty the sys privs I am missing here.

I split points between you guys....



Most likely, the privilege you were missing was "GLOBAL QUERY REWRITE".
I have to face the problem as well and searched it solution frm  the site below:

In summary:
CREATE ANY INDEX must be explicitly granted to your Oracle user, not via a role!



Site:  http://forums.oracle.com/forums/thread.jsp?forum=75&thread=249256&message=727594&q=20696e73756666696369656e742070726976696c65676573#727594
Interestingly enough, it's actually the CREATE TABLE priv that was missing.
Actually, it's both CREATE TABLE and UNLIMITED TABLESPACE that were missing.  I just did this procedure with RESOURCE role, CREATE SESSION, UNLIMITED TABLESPACE, and CREATE TABLE system privs.