Oracle stored procedure DB Link question - oracle

I have a stored procedure FOO belonging to user A. User B has EXECUTE permission on FOO.
One of the procedures in FOO uses a DB Link to retrieve data from BARTABLE#REMOTEDB. A has a DB Link to REMOTEDB connecting as user AREMOTE while B has a DBLink with the same name connecting to REMOTEDB but as user BREMOTE.
When B executes FOO, will it use A's DB Link (connecting as AREMOTE) or B's DB Link (Connecting as BREMOTE)?
I ask because I assumed a procedure belonging to a particular user would only have access to that user's dblinks even if another user had EXECUTE on that procedure. But somehow this procedure is working properly even though the user AREMOTE does not have SELECT on BARTABLE#REMOTEDB, so I'm confused.

The procedure should use the dblink that is defined for A's link. Any oracle procedure uses the rights of the owner to process, except where that procedure has been defined with "Invoker's Rights". Invoker's Rights
Invoker's rights defined for a procedure tells the code to use the rights and objects local to the calling user, and not the code owner. The reason that this is not done by default is typically an end user will have no rights to any hard objects for direct update, but be given proper access through an API, which would apply the correct business logic to updates, inserts and deletes, and then these objects would be exposed as accessible to the end user.

Related

Create stored procedure in Oracle with Roles privileges

I have a problem with creating a stored procedure.
I have permissions to the table XYZ through Roles, so when I do a SELECT to the table XYZ I don't have problem, but when I want to create a stored procedure (inside my code I call to the table XYZ table) Oracle tell me:
Table or view doesn't exist.
When another user who have directly permissions for table XYZ create the stored procedure with the same code don't have problems.
So I hope you could help me. I think I need to assign another kind of permission to the Role that I use.
From the documentation:
How Roles Work in PL/SQL Blocks
Role behavior in a PL/SQL block is determined by the type of block and
by definer's rights or invoker's rights.
Roles Used in Named Blocks with Definer's Rights
All roles are disabled in any named PL/SQL block that executes with
definer's rights.
Roles Used in Named Blocks with Invoker's Rights and Anonymous PL/SQL
Blocks
Named PL/SQL blocks that execute with invoker's rights and anonymous
PL/SQL blocks are executed based on privileges granted through enabled
roles.
Roles Used in Named Blocks with Definer's Rights
All roles are disabled in any named PL/SQL block that executes with
definer's rights.
Examples of named PL/SQL blocks are stored procedures, functions, and
triggers.
Roles are not used for privilege checking and you cannot set roles
within a definer's rights procedure.
This is from the 19c documentation, but it has been true pretty much forever.
You only have 2 solutions:
either your Oracle user is granted the direct privilege on the table (ie without a role)
or you create a stored procedure with invoker rights.
Here is an example of invoker right procedure.
Use AUTHID CURRENT_USER clause and access table SCHEMA.XYZ with dynamic SQL because invoker rights are not enabled at PL/SQL compilation time but only at PL/SQL run time.
create or replace procedure myproc
authid current_user
as
l number;
begin
execute immediate 'select c from schema.xyz where rownum = 1' into l;
dbms_output.put_line('l= ' || l);
end;
/

Oracle - Stored Procedure with same name across multiple schema - Which would be called by default

If there is a stored procedure across different schemas (SYS, User defined Schema), which schema would be called by default if we don't mention a Schema Name.
**Schema_1**
Sample_SP
**Schema_2**
Sample_SP
**SYS**
Sample_SP
execute Sample_SP
Which schema would be executed?
It depends on how you call the procedure. If you use the simple name (meaning: not prefixed by the schema name), then Oracle will only look in the current schema. To call the procedure from any other schema, you must use the qualified name. If you call the procedure using the simple name, and a procedure by that name does not exist in your schema, you will get an error - you will not get a "default" place to look in. And, of course, if you use a qualified name to call it from a different schema, but you don't have the required privileges, you will get an error as well.
You may also create a synonym, but that can only be pointed (in the synonym definition) to one of the procedures - in one specific schema.
If you are connected as user schema_1, then its procedure would be executed.
Others might, or might not ever be executed, depending on whether their owners granted you execute privilege on their procedures and whether there are (public or private) synonyms.
But, the bottom line is: first execute your own code, then - if it doesn't exist - search for it elsewhere.
It will execute the stored procedure from connected schema.
Stored procedure from SYS will be executed if there is no user defined schema is connected as SYS is default.

Insert data in a table in another schema from a materialized view using a procedure in Oracle

I've been trying to insert data from a materialized view into a table that belongs to a different scheme using a procedure, but when I compile the procedure I get the error of: table or view doesn't exist. I have checked and I have selection and insertion privileges on that table. create or replace PROCEDURE PROCEDURE_MYPROCEDURE AS
BEGIN
INSERT INTO SCHEME.TABLE
(COLUMN1,COLUM2)
SELECT COLUMN1,COLUMN2
FROM MATERIALIZED_VIEW;
END PROCEDURE_MYPROCEDURE;
this line SCHEME.TABLEshows the message "PL/SQL: STATEMENT IGNORED", "TABLE OR VIEW DOES NOT EXIST"
The most likely cause is that you have access via a role not directly, which means you can run it in SQL but for a PLSQL procedure you need a direct privilege granted.
As per the Application Developer guide:
Privileges Required to Create Procedures and Functions
To create a stand-alone procedure or function, or package specification or
body, you must meet the following prerequisites:
You must have the CREATE PROCEDURE system privilege to create a
procedure or package in your schema, or the CREATE ANY
PROCEDURE system privilege to create a procedure or package in
another user’s schema.
Attention: To create without errors, that is, to compile the procedure
or package successfully, requires the following additional privileges:
The owner of the procedure or package must have been explicitly
granted the necessary object privileges for all objects referenced within
the body of the code; the owner cannot have obtained required
privileges through roles.
If the privileges of a procedure’s or package’s owner change, the procedure
must be reauthenticated before it is executed. If a necessary privilege to a
referenced object is revoked from the owner of the procedure (or package), the
procedure cannot be executed.
An easy way to test things is:
SQL> set role none;
SQL> "statement you want to test to see if it'll work in a procedure"
So you might just be missing some direct grants on those objects.
If the procedure is compiled on user a and the MATERIALIZED_VIEW is owned by user b. When you execute the procedure it will look for the materialized view on user a.
Put the user/schema in front of the MATERIALIZED_VIEW.
You would also need to grant select on MATERIALIZED_VIEW to user a.

Bypass "table or view does not exist" in package compilation

There are two schemas in a Oracle database.
MYSCHEMA that is controlled by me.
OTHERSCHEMA that is not controlled by me.
I just know I can get result from select * from OTHERSCHEMA.OTHEROBJECT. However, OTHEROBJECT is a synonym.
In my package, I have a statement like
insert into MYSCHEMA.MYTABLE(COL1) select COL1 from OTHERSCHEMA.OTHEROBJECT;
But it gave me Table or view does not exist.
How can I solve or bypass this problem? Thanks!
I assume you received the privilege to select from otherschema.otherobject by means of a role as opposted to a direct grant (such as grant all on otherschema.otherobject to myschema). If this is the case, the privileges within this role will not be used to determine what rights you have within a PL/SQL block.
See also How Roles Work in PL/SQL Blocks (Oracle Docu, where it says under Roles Used in Named Blocks with Definer's Rights:
All roles are disabled in any named PL/SQL block (stored procedure, function, or trigger) that executes with definer's rights. Roles are not used for privilege checking and you cannot set roles within a definer's rights procedure.)

Oracle Syntax for Creating Database Link Owned by Another User

The typical syntax for creating a db link is as follows:
create database link remote_db_link
connect to remote_user
identified by remote_password
using 'remote_db'
But I'd like my DB link owned by another account after it's created. Is there a way to do this?
The following does NOT work:
create database link anotheruser.remote_db_link
connect to remote_user
identified by remote_password
using 'remote_db'
Sathya is correct, in that the CREATE DATABASE LINK syntax does not allow creating a database link in another schema. HOWEVER...
WORKAROUND
It IS possible to create a database link in another user's schema, as long as anotheruser has CREATE DATABASE LINK privilege, and the user you are connected as has CREATE ANY PROCEDURE privilege.
Here's the workaround I use:
create procedure anotheruser."tmp_doit_200906121431"
is
begin
execute immediate '
create database link remote_db_link
connect to remote_user
identified by remote_password
using ''remote_db'' ';
end;
/
begin
anotheruser."tmp_doit_200906121431";
end;
/
drop procedure anotheruser."tmp_doit_200906121431"
/
Let's unwind that. First, I create a procedure in the anotherusers's schema; this procedure contains the CREATE DATABASE LINK statement that I want to run.
When the procedure is executed, it runs as the owner of the procedure, such that the CREATE DATABASE LINK statement is executed by anotheruser.
The name of the procedure is not important, except that I need to make sure that it doesn't conflict with any existing object name. I use lowercase letters (enclosing the procedure name in double quotes), using "tmp" to mark this object as "temporary", and using the current yyyymmddhh24miss as the part of the procedure name. (I usually run a query of DBA_OBJECTS to check that a matching object_name does not exist.)
For a "one-off" type admin function, this is a viable workaround. I prefer this to the other alternative: saving the anotheruser's password, changing the password, connecting as the user, and resetting anotheruser's password back to the saved.)
Restrictions on DBLinks - You cannot create a database link in another user's schema, and you cannot qualify dblink with the name of a schema.
AS a sys user you can view all db links in SYS.DBA_DB_LINKS view.
That view use link$ and user$ table.
You can create new dblink as usually and it show at link$ table. Then change owner (use id from user$). commit. Done.

Resources