I want to get the DDL of Table CARD_TABLE in XT schema
SQL> select dbms_metadata.get_ddl('TABLE','CARD_TABLE','XT') from dual;
ERROR:
ORA-31603: object "CARD_TABLE" of type TABLE not found in
schema "XT"
ORA-06512: at "SYS.DBMS_METADATA", line 5746
ORA-06512: at "SYS.DBMS_METADATA", line 8333
ORA-06512: at line 1
But my select Query works
select count(*) from XT.CARD_TABLE;
count(*)
---------
0
I queried dba_objects it still got the table:
SQL> select owner,object_type from DBA_OBJECTS
where object_name='CARD_TABLE' 2
3 ;
PUBLIC SYNONYM
XT TABLE PARTITION
XT TABLE PARTITION
XT TABLE PARTITION
XT TABLE
XT TABLE PARTITION
VAT TABLE
7 rows selected.
From the dbms_metadata documentation:
If nonprivileged users are granted some form of access to an object in someone else's schema, they will be able to retrieve the grant specification through the Metadata API, but not the object's actual metadata.
So unless you're connected as a privileged user, you can't see the DDL for another user's objects. You would need to connect as SYS, or have the SELECT_CATALOG_ROLE role granted to your user to be able to get XT's object definition.
Even with that role:
In stored procedures, functions, and definers-rights packages, roles (such as SELECT_CATALOG_ROLE) are disabled. Therefore, such a PL/SQL program can only fetch metadata for objects in its own schema. If you want to write a PL/SQL program that fetches metadata for objects in a different schema (based on the invoker's possession of SELECT_CATALOG_ROLE), you must make the program invokers-rights.
If you're calling dbms_metadata from an anonymous PL/SQL block that doesn't matter, but if you're calling it from a procedure you will have to include an AUTHID clause in the procedure declaration, adding AUTHID CURRENT_USER.
grant SELECT_CATALOG_ROLE to <user> with delegate option;
it work for me. Do this after modify procedure
grant SELECT_CATALOG_ROLE to procedure <procedure name>;
Related
I created a procedure
create or replace procedure dba_role
as
user varchar2(200);
ref varchar2(200);
begin
insert into dba_role_privs(grantee,granted_role) (select user as grantee,granted_role from dba_role_privs where grantee=ref);
end;
The procedure is getting created but I'm not able to execute the procedure. I've tried different methods to execute it by passing parameters but nothing worked.
Can anyone please tell how to execute this procedure in oracle live SQL
the parameters to be passed are both strings(varchars)
for example:
I've tried "Execute dba_role('alex','hunter');
The error is
**ORA-06550: line 1, column 7:
**PLS-00306: wrong number or types of arguments in call to 'DBA_ROLE' **
As well as missing the two parameters that you are trying to pass (parameters should appear in brackets immediately following the procedure name, as explained in d r's answer), you can't insert into a DBA view. For one thing, it's not in your schema (unless you are creating your procedure as SYS, which you should never do because SYS is reserved for Oracle internals) and you haven't been granted INSERT privilege, but also because it is defined with multiple joins and unions etc and is therefore not an updatable view. Even it it were, your procedure only specifies two of its seven columns.
Even if you did have privileges and it was updatable and you supplied all of the values, directly updating internal data dictionary tables is unsupported and could damage your database. If you want to grant a privilege to a role you should use the GRANT command:
grant reports_user to hr;
To revoke the grant,
revoke reports_user from hr;
create or replace procedure
dba_role(p_user IN VarChar2, p_ref IN VarChar2) AS
begin
insert into dba_role_privs(grantee, granted_role) (select p_user as grantee, granted_role from dba_role_privs where grantee = p_ref);
end dba_role;
/
Above is how it should be defined - with two VarChar2 parameters. And below is how to call it:
Begin
dba_role('alex', 'hunter');
End;
/
The problem with your code was that user and ref were declared as variables within the scope of the procedure (not as parameters) so, when the procedure was called with parameters (like I did above) then you tryed to pass two parameters to the procedure not accepting any. On the other side, if you call it without parameters (just as dba_role;) then user and ref were both Null.
I am using Oracle and SQL Developer. I have a table called T_TEST owned by SYSTEM (I know, that I shouldn't do it, but it's not a commercial project). I created another user and gave him this privileges:
GRANT CONNECT TO admin1;
GRANT CREATE SESSION TO admin1;
GRANT SELECT ON T_TEST TO admin1;
When I run this query I get the expected result:
SELECT SUM(value) FROM SYSTEM.T_TEST;
However, when I try to wrap this query in a transaction like this:
CREATE PROCEDURE reader
AS
BEGIN
SET TRANSACTION READ ONLY;
SELECT SUM(value) FROM SYSTEM.T_TEST;
COMMIT;
END;
I get this error:
ORA-01031: insufficient privileges
So which privilege am I missing here?
You are missing grants to create a procedure. You can do that by following the below command -
GRANT CREATE PROCEDURE TO [domain\user]
This link has a whole list of permissions that you can grant to the users. Enjoy your project.
UPDATED question:
The core of my problem is: The stored procedure I (User1) created is not able to select from the some specific table (table1 created by another user (User2)) due to:
CREATE OR REPLACE PROCEDURE TEST_SCHEMA.TEST_PROCEDURE(OUT r_count INTEGER)
LANGUAGE SQL
BEGIN
SET r_count = (SELECT COUNT(*) FROM TEST_SCHEMA.TABLE1);
END
OK. No rows were affected
SQLWarning: Code: 20480 SQL State: 0168Y
--- The newly defined object "TEST_SCHEMA.TEST_PROCEDURE" is marked as invalid because it references an object "TEST_SCHEMA.TABLE1" which is
not defined or is invalid, or the definer does not have privilege to
access it.. SQLCODE=20480, SQLSTATE=0168Y, DRIVER=4.22.29
However, when I select from table1 in a normal query window there is no problem, hence I thought something was wrong about the security option on the stored procedure
SELECT COUNT(*) FROM TEST_SCHEMA.TABLE1
Table and stored procedure names are fully qualified. The stored procedure is created and executed by user1. The privilege given to the user1, to select from table1 , is a group privilege.
The procedure creator must have the corresponding privilege on statically referenced table either directly or via roles.
CREATE PROCEDURE (SQL) statement:
Authorization
The privileges held by the authorization ID of the
statement must include at least one of the following authorities:
If the implicit or explicit schema name of the procedure does not exist, IMPLICIT_SCHEMA authority on the database.
If the schema name of the procedure refers to an existing schema, CREATEIN privilege on the schema.
DBADM authority
The privileges held by the authorization ID of the statement must also
include all of the privileges necessary to invoke the SQL statements
that are specified in the procedure body.
To replace an existing procedure, the authorization ID of the
statement must be the owner of the existing procedure (SQLSTATE
42501).
Group privileges are not considered for any table or view specified in
the CREATE PROCEDURE (SQL) statement.
I am struggling with schemas while creating a stored procedure in DB2 database ( 10.5 version ).
My user name is XYZ but I have to create a Stored procedure for schema ABC.
When I am trying to execute the create procedure sql I get error message which looks like Schema related
Create procedure ABC.customInsert(
IN temp INTEGER
)
BEGIN
INSERT INTO ABC.One_Column_table VALUES ( temp );
END
Error Message:
Error:DB2 SQL error:SQLCODE:-551, SQLSTATE: 42501,
SQLERRMC:XYZ;INSERT;ABC.One_Column_table
My current schema was showing XYZ earlier. ( result of select current_Schema from sysibm.sysdummy1).
I have changed it to ABC. ( using SET CURRENT SCHEMA ABC). But still the same problem.
I am able to insert, select, create UDT etc in ABC schema but the problem exists only during stored procedure creation.
Any idea what am I doing wrong ?
Based on your error message, SQLCODE -551 means that the user "XYZ" does not have the "INSERT" privilege on the table "ABC.One_Column_table".
Since you imply that you, when connected as XYZ, can insert into the table by issuing simple INSERT statements, it is possible that you possess the INSERT privilege indirectly, via a group membership. Group privileges are ignored for SQL statements in stored procedures, functions or triggers, as explained in this IBM technote.
You have two options:
Grant the required privileges on ABC.One_Column_table to the user XYZ directly.
Create a role (using the CREATE ROLE statement), grant the table privileges to that role, then grant the role to the user XYZ.
If you are curious, such behaviour is caused by the fact that static SQL statement (e.g. in a stored procedure) authorization is checked only during compilation, and the compiled code can then be executed without additional authorization checks. Groups are maintained outside the DB2 database, by the operating system, and it is possible that group membership changes after the stored procedure is compiled and without the database security administrator's knowledge. If group privileges were effective for static SQL, it would allow users who weren't originally authorized to run particular statements (i.e. were not members of the authorized group at the compilation time) still execute those statements, thus creating a security risk.
Roles, on the other hand, are maintained within the database itself by the database security administrator and thus are part of the same security landscape.
Simply querying running jobs using something like
select * from dba_jobs_running;
works fine when executed in my sqldevelopers SQL console.
However, it does not work, when having exactly the same statement within a procedure.
Compilation fails with
PL/SQL: ORA-00942: table or view does not exist
Any ideas? Is there something like a scope to be considered?
Any suggestions are highly appreciated, thanks in advance :)
You probably need to do a direct GRANT of DBA_JOBS_RUNNING to the user that owns the procedure. Doing a GRANT via a role won't work.... the grant needs to be explicit.
EDIT:
Doing a SELECT from within a procedure requires subtly different permissions to doing a SELECT from outside a procedure (e.g. in SQL-Developer). The user that owns a procedure must have been explicitly granted rights to the table or view... if running a query from outside a view this is not the case (you can be granted the permission through a role for example)
You need to connect as SYS and go:
GRANT SELECT ON SYS.DBA_JOBS_RUNNING TO <user-that-owns-proc>;
Procedures are executed without roles. One way to see if you can run a command in a procedure is to execute:
SQL> set role none;
Role set
You will have the same set of rights as your procedures:
SQL> SELECT * FROM dba_jobs_running;
SELECT * FROM dba_jobs_running
ORA-00942: table or view does not exist
You have to grant select on the view directly to the user:
SQL> -- with dba account
SQL> grant select on dba_jobs_running to a;
Grant succeeded
You will then be able to compile the procedure:
SQL> -- with application schema
SQL> CREATE OR REPLACE PROCEDURE test_dba AS
2 BEGIN
3 FOR cc IN (SELECT * FROM dba_jobs_running) LOOP
4 NULL;
5 END LOOP;
6 END test_dba;
7 /
Procedure created
Is procedure owned by another user? If so have a look at:
Definer and Invoker Rights for stored routines in PL/SQL manual.
Rob