I have a simple stored procedure that is calling dbms_metadata.get_ddl. The stored procedure is owned by UserA and it is trying to get the ddl for UserB.
create or replace PROCEDURE usera.get_ddl
(p_table_owner VARCHAR2,
p_table_name VARCHAR2)
IS
l_ddl clob;
BEGIN
SELECT dbms_metadata.get_ddl ('TABLE',
upper(p_table_name),
upper(p_table_owner))
INTO l_ddl
FROM dual;
END get_ddl;
/
Userb has the following table:
create table userb.a ( a number, b varchar2(10));
Execute the stored procedure:
SQL> exec usera.get_ddl('userb','a');
BEGIN usera.get_ddl('userb','a'); END;
*
ERROR at line 1:
ORA-31603: object "a" of type TABLE not found in schema "userb"
ORA-06512: at "SYS.DBMS_METADATA", line 5805
ORA-06512: at "SYS.DBMS_METADATA", line 8344
ORA-06512: at line 1
ORA-06512: at "USERA.GET_DDL", line 7
ORA-06512: at line 1
Option 2:
1- Create the procedure in the SYS schema
2- Grant execute on the procedure to the chosen users.
create or replace PROCEDURE usera.get_ddl
(p_table_owner VARCHAR2,
p_table_name VARCHAR2)
IS
l_ddl clob;
BEGIN
SELECT dbms_metadata.get_ddl ('TABLE',
upper(p_table_name),
upper(p_table_owner))
INTO l_ddl
FROM dual;
END get_ddl;
/
Userb has the following table:
create table userb.a ( a number, b varchar2(10));
Execute the stored procedure:
SQL> exec usera.get_ddl('userb','a');
BEGIN usera.get_ddl('userb','a'); END;
*
ERROR at line 1:
ORA-31603: object "a" of type TABLE not found in schema "userb"
ORA-06512: at "SYS.DBMS_METADATA", line 5805
ORA-06512: at "SYS.DBMS_METADATA", line 8344
ORA-06512: at line 1
ORA-06512: at "USERA.GET_DDL", line 7
ORA-06512: at line 1
So first off user a needs the following grant:
grant select_catalog_role to usera;
Even after this the execute still gives the same error.
This error is due to Oracle Bug: 3960099 - ORA-31603 WHEN CALLING DBMS_METADATA FROM PROCEDURE
There are 2 work arounds given by Oracle:
Option 1:
1- Create the procedure with AUTHID CURRENT_USER
2- Grant SELECT ANY DICTIONARY privilege to any user calling the procedure
OR
2- Grant SELECT ANY DICTIONARY privilege to any user calling the procedure
OR
Option 2:
1- Create the procedure in the SYS schema
2- Grant execute on the procedure to the chosen users.
I chose Option 1 as this way there is no need to create a SYS stored procedure:
create or replace PROCEDURE usera.get_ddl
(p_table_owner VARCHAR2,
p_table_name VARCHAR2)
AUTHID CURRENT_USER
IS
l_ddl clob;
BEGIN
SELECT dbms_metadata.get_ddl (
'TABLE',
upper(p_table_name),
upper(p_table_owner))
INTO l_ddl
FROM dual;
END get_ddl;
/
Give the grant:
grant select any dictionary to usera;
(p_table_owner VARCHAR2,
p_table_name VARCHAR2)
AUTHID CURRENT_USER
IS
l_ddl clob;
BEGIN
SELECT dbms_metadata.get_ddl (
'TABLE',
upper(p_table_name),
upper(p_table_owner))
INTO l_ddl
FROM dual;
END get_ddl;
/
Give the grant:
grant select any dictionary to usera;
Now execute the stored procedure:
SQL> exec usera.get_ddl('userb','a');
PL/SQL procedure successfully completed.
Thanx!!
ReplyDeleteHelped me a lot!!
Thanks !! Its one of the rare articles on this issue available out there. Every other forum, article, blogpost simply say "grant select_catalog_role to the user".
ReplyDeleteYou've actually addressed a very unique issue that doesn't have an obvious solution!
Thank you !
another option is to use ALL_SOURCE TO fetch the stored proc code:
ReplyDeletedeclare
v_sql clob;
begin
v_sql := 'CREATE OR REPLACE ';
for rec in (SELECT upper(text) as text
FROM ALL_SOURCE
WHERE name=&proc_name
and type=&proc_type
ORDER BY LINE)
loop
v_sql := v_sql || rec.text;
end loop;
dbms_output.put_line(v_sql);
end;
Baccarat: Rules & Payouts | Best Baccarat Sites - febcasino
ReplyDeleteThere are download youtube videos many ways to play baccarat in Las Vegas. First, you can play the online casino or find an online baccarat table with 제왕카지노 real dealers. Then, you febcasino can