Oracle Procedure - oracle

create or replace function gen.sample_func(owner varchar2) return varchar2
as
data_t varchar2(10);
cursor cur is select data_type from SYS.DBA_TAB_COLUMNS;
begin
open cur;
dbms_output.put_line('Done');
close cur;
return data_t;
end sample_func;
On compiling the above function i get the following error
Warning: compiled but with compilation errors
Errors for FUNCTION sample_func
LINE/COL
--------------------------------------------------------------------------------
ERROR
--------------------------------------------------------------------------------
4/8
PLS-00201: identifier 'DBA_TAB_COLUMNS' must be declared
4/8
PL/SQL: Item ignored
7/15
PLS-00320: the declaration of the type of this expression is incomplete or malfo
rmed
7/8
PL/SQL: Statement ignored
I'm not getting this error when i execute the select statement alone in the cursor.
Please help me to resolve this issue.

Your user needs to be granted SELECT ON DBA_TAB_COLUMNS.
Note that granting through a role will not work - it needs to be a direct grant to the user for you to create a function/procedure.

In a definer's rights stored procedure such as the one you are creating, only privileges that are granted directly to the owner of the procedure are considered when resolving object names. Privileges granted through roles are not considered. I would wager that the owner of your procedure has been granted access to the DBA_TAB_COLUMNS view via a role rather than via a direct grant. You would need to ask the DBA to grant access to DBA_TAB_COLUMNS directly to the user that owns your procedure.
You can quickly test whether this is actually the problem you're experiencing. In SQL*Plus, enter the command
SQL> set role none;
and then run your SELECT statement. If you get the same permissions error, then the rpoblem is that you have the grant via a role. Disabling roles means that your interactive session is running with the same privileges that your stored procedure would run with.

Related

PL/SQL: ORA-01031: insufficient privileges 6/1 PL/SQL: SQL Statement ignored GRANT

Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production
I'm getting the above message when trying to create a package.
I can simulate with a very simple procedure and select statement.
My understanding is that have SQL select access for a user does not translate to PL/SQL (package) access for the same user, and that an option is to use roles. This has not worked for me.
This is all done with the same user (not apex_180100).
Showing the issue:
This SQL works. It doesn't make sense, but proves that I can select from the tables.
SELECT 1
FROM apex_180100.wwv_flow_activity_log l,
apex_180100.wwv_flow_worksheet_rpts r
WHERE l.ir_report_id IS NOT NULL
AND l.flow_id = 100
AND l.worksheet_id = r.worksheet_id
AND l.ir_report_id = r.id
AND l.flow_id = r.flow_id
AND l.step_id = r.page_id;
I granted select to a role
GRANT SELECT ON apex_180100.wwv_flow_worksheet_rpts TO PRIV_FULL_TABLE;
GRANT SELECT ON apex_180100.wwv_flow_activity_log TO PRIV_FULL_TABLE;
I grant my role to my procedure (ultimately I will grant to my package)
GRANT PRIV_FULL_TABLE TO PROCEDURE p_test;
I get an error when creating this simple sample procedure.
create OR REPLACE procedure p_test is
V_TEST NUMBER;
begin
SELECT 1
INTO V_TEST
FROM apex_180100.wwv_flow_activity_log l,
apex_180100.wwv_flow_worksheet_rpts r
WHERE l.ir_report_id IS NOT NULL
AND l.flow_id = 100
AND l.worksheet_id = r.worksheet_id
AND l.ir_report_id = r.id
AND l.flow_id = r.flow_id
AND l.step_id = r.page_id;
end;
PL/SQL: ORA-01031: insufficient privileges compilation error
Hm, there's something strange in what you are saying. Usually we grant privileges to users, not procedures.
SQL> create procedure p_test as begin
2 null;
3 end;
4 /
Procedure created.
SQL> create role priv_full_table;
Role created.
SQL> grant priv_full_table to procedure p_test;
grant priv_full_table to procedure p_test
*
ERROR at line 1:
ORA-00991: only MAC privileges may be granted to procedures
SQL>
Apart from that, if I understood you correctly, issue is exactly what you thought that solves it: privileges granted to roles won't work in named stored procedures. p_test is a named procedure:
create OR REPLACE procedure p_test is ...
which means that you'll have to grant those privileges directly to user which will be using them.
Thanks to #Littlefoot
I used a workaround. My procedure is relatively simple, I wanted to insert into a custom table from my "problem" tables. I wanted this to be called by an hourly DB job.
As I can select and insert in SQL, but not PL/SQL procedures, I used a SQL script instead of datbase procedure.
i.e I converted my package into a series of SQL statements. I stored this sql script on the server and ran as a DBA job executable.
Not ideal.
PS 'execute immediate' doesn't work either.

As a system user I have this error: ORA-01031: insufficient privileges

I have a stored procedure for deleting partitions. Before starting, I have to delete a constraint.
I installed the stored procedure on system user. When I test the procedure I have this error: 'ORA-01031: insufficient privileges'.
This is a piece of code that I wrote:
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE USER_NAME.TABLE_NAME DISABLE CONSTRAINT CONSTRAINT_NAME';
EXCEPTION
WHEN OTHERS THEN
O_sCodError := 'NO_OK';
O_sDesError := 'Error at DISABLE CONSTRAINT_NAME: ' || SQLERRM || ';';
RETURN;
END;
Well, as I execute the stored procedure as system, I do not understand the reason for I have that error. And I think I eventually think the same error when I try to delete a partition.
Works for me on 11g XE:
SQL> show user
USER is "SCOTT"
SQL>
SQL> create table test
2 (id number constraint pk_test primary key,
3 name varchar2(20)
4 );
Table created.
SQL> connect system
Enter password:
Connected.
SQL> begin
2 execute immediate 'alter table scott.test disable constraint pk_test';
3 return;
4 end;
5 /
PL/SQL procedure successfully completed.
SQL>
Please, follow that example and execute it in your database. Post the result (by editing the question, not as a comment).
First, you should never install custom code in an Oracle default schema like SYSTEM. Put your code in a dedicated application schema. Since it contains dynamic SQL (execute immediate) you might want to consider making it an "invoker's rights" procedure, then granting execute privileges on it to the user that will execute it.
That said, in Oracle 11g whoever's privileges are used to run the PL/SQL block must have direct permissions on the underlying table, not inherited permissions through a role like DBA. If the procedure has "definer's rights" then the schema that owns the procedure must have direct privileges on the table. If "invoker's rights" then the user executing the procedure must have the privileges.
See this link for additional details:
Execute immediate within Oracle Procedure
You must grant SYSTEM account direct privilege (not with a role) to run ALTER TABLE on the target table because roles are not enabled in stored procedures by default: https://asktom.oracle.com/Misc/RolesAndProcedures.html.
Try:
grant alter any table to system;
or
grant alter table on user_name.table_name to system;

How to access the HR schema objects through a user defined procedure in Oracle 18c? [duplicate]

This question already has answers here:
Why doesn't PL/SQL respect privileges granted by Roles?
(5 answers)
ORA 904 - Error compiling function that references function from another schema - has execute privilege
(1 answer)
Closed 3 years ago.
I have given the code and the error messages I got when I try to create a procedure being user1. I try to access employees table in the sample hr schema in Oracle XE 18c. Can I know how to access hr schema objects via a user defined procedures
CREATE OR REPLACE PROCEDURE proc_1 IS
v_name hr.employees.first_name%TYPE;
v_num NUMBER;
BEGIN
SELECT first_name INTO v_name FROM hr.employees
WHERE employee_id=100;
v_num:=5;
DBMS_OUTPUT.PUT_LINE('test'||v_name);
DBMS_OUTPUT.PUT_LINE(v_num);
END;
/
Warning: Procedure created with compilation errors.
SQL> show errors
Errors for PROCEDURE PROC_1:
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/8 PL/SQL: Item ignored
2/8 PLS-00201: identifier 'HR.EMPLOYEES' must be declared
5/1 PL/SQL: SQL Statement ignored
5/39 PL/SQL: ORA-00942: table or view does not exist
7/1 PL/SQL: Statement ignored
7/38 PLS-00320: the declaration of the type of this expression is
incomplete or malformed
You will need to grant access to HR objects to user user1.
Connected as user HR:
grant select on employees to user1;
You need to give a select grant of the hr.employees table directly.
From the HR user, you need to execute:
grant select on employees to user1;
Grant of hr.employees given to your user via role will not be considered when PL/SQL program(procedure/function/etc..) is executed with definer's right.
The use of roles in a subprogram depends on whether it executes with
definer rights or invoker rights. Within a definer-rights subprogram,
all roles are disabled.
Find it in Oracle documentation here.
Cheers!!

Oracle: my DML for Index recreation puzzle

Problem anamnesis:
In order to automate index recreation for a PVJOURNAL table in oracle I wrote a procedure in a package.
The table PVJOURNAL locates in PROVIEW schema. My SPACEMAN user has enough grants in that schema. Here below is a DDL of the package:
CREATE OR REPLACE
PACKAGE spaceman.tmp_itcm4052 is
-- This proc rebuilds ALL indexes of a specific.
PROCEDURE idx_rebuild;
END;
/
CREATE OR REPLACE
PACKAGE BODY spaceman.tmp_itcm4052 is
-- ===========================================================================
PROCEDURE idx_rebuild as
-- This proc rebuilds ALL indexes of a specific table. Run by Job
v_sql_str VARCHAR2(200);
begin
FOR rec in (
select owner ||'.'|| index_name as IDX_NAME,
tablespace_name as TblSpace
from sys.all_indexes
where upper(index_type) = 'NORMAL'
and upper(table_owner) = 'PROVIEW'
and upper(table_name) in ('PVJOURNAL')
)
LOOP
v_sql_str := 'ALTER INDEX '||rec.IDX_NAME||' rebuild tablespace '
||rec.TblSpace||' online';
-- ALTER INDEX ... SHRINK SPACE COMPACT
-- ALTER INDEX ... DEALLOCATE UNUSED SHRINK SPACE COMPACT
dbms_output.put_line('v_sql_str = '||v_sql_str);
execute immediate v_sql_str;
commit;
END LOOP;
end idx_rebuild;
END tmp_ITCM4052;
/
Problem itself:
The problem is that a call of the procedure under my SPACEMAN user
begin
spaceman.tmp_itcm4052.idx_rebuild;
end;
ends up with error
ORA-01031: insufficient privileges - full view of the error
But the direct run of the line, produced by the procedure, saved into v_sql_str variable and visualized by this piece of the procedure:
dbms_output.put_line('v_sql_str = '||v_sql_str);, done under the same SPACEMAN user works like a magic. proof that direct alter does work
Questions:
What wrong have I done to the gods of pl/sql? Why the call to the procedure fails whilst the same command, execurted directly - is not?
UPD: Not only GRANT INDEX ON PROVIEW.PVJOURNAL TO SPACEMAN; didn't help. Moreover, for whatewer reason not yet kown to me, GRANT ALTER ANY INDEX to SPACEMAN; didn't help either.
Had doublechecked it with
SELECT PRIVILEGE
FROM sys.dba_sys_privs
WHERE upper(grantee) = 'SPACEMAN'
UNION
SELECT PRIVILEGE
FROM dba_role_privs rp JOIN role_sys_privs rsp ON (rp.granted_role = rsp.role)
WHERE upper(rp.grantee) = 'SPACEMAN'
ORDER BY 1;
the privilege ALTER ANY INDEX (as well as ALTER ANY INDEXTYPE ) is in the list.
UPD 1: as it turned out - the ALTER ANY INDEX privilege is not sufficient in this case. What did helped me is that link, kindly provided by #Wernfried Domscheit. REspect, man!
The procedure created as
CREATE OR REPLACE
PACKAGE spaceman.tmp_itcm4052 authid CURRENT_USER is
works like a spell.
Inside a PL/SQL block you have only privileges which are granted to the user directly. Privileges which are granted by ROLE (e.g. DBA) do not apply inside a PL/SQL block (except role PUBLIC).
Grant CREATE ANY INDEX directly to the user, then it should work.
The behavior described above is the default, it is called "definer's rights unit". You can change it by adding AUTHID CURRENT_USER to your procedure/package. For more information see Invoker's Rights and Definer's Rights (AUTHID Property)
N.b. COMMIT is not required after a DDL statement. Oracle performs an implicit commit.
Different grants are used when you invoke direct SQL and when it is used in the procedure.
Privileges granted through a role (such as DBA) are not available to
definer's rights stored procedures which is the default.
Only privileges that are granted directly to the user are available in a
definer's rights stored procedure.
You must grant the ALTER ANY INDEX privileges directly to your user.
Cheers!!

PL/SQL function in Oracle cannot see DBMS_AQ

I have problem with Oracle 9.2 and JMS.
I created PL/SQL routine to send XML text (from file or CLOB) to queue,
but this routine do not compile.
My code looks like (filling message omitted):
create or replace procedure jms_test(msg varchar2)
is
id pls_integer;
message sys.aq$_jms_stream_message;
enqueue_options dbms_aq.enqueue_options_t;
message_properties dbms_aq.message_properties_t;
msgid raw(16);
java_exp exception;
v_filehandle_input utl_file.file_type;
v_newline varchar2(32767);
pragma exception_init(java_exp, -24197);
begin
message := sys.aq$_jms_stream_message.construct;
message.set_string_property('FROM', 'TEST');
id := message.clear_body(-1);
end;
And Oracle raports that:
Error(6,21): PLS-00201: identifier 'DBMS_AQ' must be declared
I looked at some newsgroups and tried all that I found, but with no success.
granted (with success) many permisions
GRANT RESOURCE TO user;
GRANT CONNECT TO user;
GRANT EXECUTE ANY PROCEDURE TO user;
GRANT aq_administrator_role TO user;
GRANT aq_user_role TO user;
GRANT EXECUTE ON dbms_aqadm TO user;
GRANT EXECUTE ON dbms_aq TO user;
GRANT EXECUTE ON dbms_aqin TO user;
desc dbms_aq shows many functions like DEQUEUE, ENQUEUE, LISTEN
executed in SQLPlus both catqueue.sql and dbmsaq.plb
Anybody have idea what can be wrong?
EDITED:
I can do all that is described in: http://rwijk.blogspot.com/2009/02/whats-in-my-jms-queue.html, so dbms_aq is somehow visible, but not in my procedure.
Does it work if you do...
SYS.DBMS_AQ
instead of just
DBMS_AQ
If so, you're missing a synonym.
EDIT:
If you're now getting "PLS-00201: identifier 'SYS.DBMS_AQ" then I'd double check your grants.
GRANT EXECUTE ON SYS.DBMS_AQ to <your-user>;
Also, just to confirm, you've granted the execute privilege directly to the user, and not via a role?
In order to use objects in stored procedures, you must have grants WITH GRANT OPTION.
In this case you smust have
GRANT EXECUTE ON SYS.DBMS_AQ WITH GRANT OPTION to ;

Resources