Skip to Main Content
  • Questions
  • Grant Access on DB_Link to other User

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Waseem.

Asked: July 11, 2016 - 5:10 pm UTC

Last updated: September 04, 2024 - 2:21 am UTC

Version: 12.1.0.2

Viewed 100K+ times! This question is

You Asked

I need to give access to other user on current DB_LINK, can you provide command ?

Current Link: sittest
Grant to User: Z9XBIQ1_DW

Regards
Chaudhry

and Connor said...

Database links are public (everyone) or private (only one).

Let's say you had this:

user A: has a db link to a remote database
user B: you want to allow access via A to object X in remote database

Then in user A, you could do (for example):

create view REMOTE_X as select * from X@dblink;

and then grant access to REMOTE_X to B.

SQL> grant connect to demo identified by demo;

Grant succeeded.

SQL> create view VVV as select * from tab@db11;

View created.

SQL> grant select on VVV to demo;

Grant succeeded.

SQL> conn demo/demo
Connected.

SQL> select * from mcdonac.vvv;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
ACCOUNT_EXTRACT                TABLE
ANY_OTHER_TABLE                TABLE
BLAH                           TABLE
...


Rating

  (9 ratings)

We're not taking comments currently, so please try again later if you want to add a comment.

Comments

thansk Tom

JUSTIN RAJU, October 11, 2018 - 9:36 pm UTC

Thanks Tom (connar) for sharing the information it did help.

how can i check how many user are accessing this Public DB link.
Connor McDonald
October 12, 2018 - 2:55 am UTC

If you run AUDIT on database links, you get records based on create/alter/drop of links. But you can also audit SELECT statements - then the audit records for the SELECT will contain information about the db link used, eg

SQL> set lines 1000
SQL> column userid format a15
SQL> column ntimestamp# format a30
SQL> column sqltext format a40
SQL> column comment$text format a200
SQL> select userid, ntimestamp#, sqltext, comment$text from aud$ where comment$text like '%DBLINK%';

USERID          NTIMESTAMP#                    SQLTEXT                                  COMMENT$TEXT
--------------- ------------------------------ ---------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------
MARK            26-OCT-15 12.49.55.219992 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 12.51.34.476959 PM   SELECT 0 FROM "GIGI" "A1"                DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 12.51.59.086081 PM   SELECT 0 FROM "GIGI" "A1"                DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.00.37.517809 PM                                            Authenticated by: DATABASE; Client address: (ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=52438)); DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.00.37.527570 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.01.36.310674 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.05.07.564925 PM                                            Authenticated by: DATABASE; Client address: (ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=52725)); DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.05.07.595509 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.08.54.204852 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.09.34.166246 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.09.59.877822 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.10.29.447086 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.10.38.853625 PM                                            DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.10.46.192234 PM                                            Authenticated by: DATABASE; Client address: (ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=53072)); DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.10.46.199130 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.10.57.918255 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.11.09.381775 PM                                            DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.11.31.318063 PM                                            Authenticated by: DATABASE; Client address: (ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=53119)); DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 01.11.31.323628 PM   SELECT "A1"."COL1" FROM "GIGI" "A1"      DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)
MARK            26-OCT-15 03.50.24.076062 PM                                            DBLINK_INFO: (SOURCE_GLOBAL_NAME=db11204.4294967295)



(Taken from MOS NOte 2071002.1)

Rachel Barker, May 07, 2021 - 2:04 pm UTC

I have been debating the easiest way to do this. As always you have a great answer. Thank you Connor!
Connor McDonald
May 10, 2021 - 7:51 am UTC

glad we could help

Flo, January 19, 2022 - 1:49 pm UTC

What if object X in the remote DB is a synonym to another user's table? It doesn't seem to work. Is it possible to do that?
Chris Saxon
January 19, 2022 - 6:36 pm UTC

You can use synonyms over db links - you still need access to the underlying objects though

Packages

Vic, October 13, 2022 - 11:09 am UTC

If you call a table via dblink its work.

But if you call a package it doesnt work.

For example.

User A:
Create view AAA as select package.function@dblink(parameter) from dual

Grant select on AAA to B

User B:
Select * from AAA

ORA-04504
Chris Saxon
October 13, 2022 - 12:30 pm UTC

What is error ORA-04504? Do you mean ORA-04054 DB link doesn't exist?

If so, have you verified the DB link name? What is the statement that does work?

Data

Vic, October 13, 2022 - 1:57 pm UTC

Thank you for your response.

Yes the error is ORA-04054.

I have a view in a schema A:

CREATE OR REPLACE FORCE VIEW AAA
(SELECT COUNT (C.COLUMN1)
FROM TABLE1@DBLINK1 C)

The dblink DBLINK1 was created in schema A.

With schema A: If I made a SELECT * FROM AAA, it works.

I grant the view to another schema called B:
GRANT SELECT ON AAA TO B

If I made a SELECT * FROM AAA, it works. Like in you example.
---

Now the same but adding a package call in where clause, for example:
CREATE OR REPLACE FORCE VIEW AAA
(SELECT COUNT (C.COLUMN1)
FROM TABLE1@DBLINK1 C
WHERE PACKAGE_NAME_FUNCTION_NAME@DBLINK1 (PARAMETER) = 'N')

With schema A: If I made a SELECT * FROM AAA, it works.

If I made a SELECT * FROM A.AAA, in schema B, it returns:
ORA-04054 database link string does not exist

It is really annoying

Thanks.

Connor McDonald
October 26, 2022 - 3:57 am UTC

Unfortunately that is just the way it is.

I'm generally not a fan of dblinks in view definitions, because if you are building a view, then you may as well build that view on the source system and then access just the view via the dblink.

Where dblink in view the better/only path

Clay, July 06, 2023 - 9:43 pm UTC

I agree with "generally not a fan of dblinks in view definitions, because if you are building a view, then you may as well build that view on the source system and then access just the view via the dblink", however, in our organization, we cannot make database links public so providing access to the link is not option. Our only option is to create the view with the embedded db link and then grant permissions to the view.

how to use dblinks of user A in dynamic sql executed by user B?

Markus H., August 22, 2024 - 11:41 am UTC

I have the following task: User A has several private database links to DB1, DB2, DB3, etc.. All databases have identical data structures. User B is to evaluate the data from the remote databases programmatically. My approach would have been to create a procedure with a loop over all remote databases in which the SQL statements for evaluating the remote data are created dynamically, whereby the database link is replaced each time the loop is run. If I have understood the previous explanations correctly, this would not be possible at the moment, right? Can you recommend an alternative?

Regards
Markus
Connor McDonald
August 23, 2024 - 8:02 am UTC

Sorry - can you elaborate a little more on

My approach would have been to create a procedure with a loop over all remote databases in which the SQL statements for evaluating the remote data are created dynamically, whereby the database link is replaced each time the loop is run

I am not following what you are stating here

Markus H., August 23, 2024 - 3:55 pm UTC

I beg your pardon, it is about USER B cyclically collecting and evaluating certain information from distributed databases in a central database. USER A owns the database links to the distributed databases. The following scripts shoud illustrate the problem:

As DBA create the user A and B:
DROP USER A CASCADE;
CREATE USER A
  IDENTIFIED BY A
  DEFAULT TABLESPACE USERS
  TEMPORARY TABLESPACE TEMP
  PROFILE DEFAULT
  ACCOUNT UNLOCK;

GRANT RESOURCE TO A;
ALTER USER A DEFAULT ROLE NONE;

-- 2 System Privileges for A 
GRANT CREATE DATABASE LINK TO A;
GRANT CREATE SESSION TO A;

CREATE USER B
  IDENTIFIED BY B
  DEFAULT TABLESPACE USERS
  TEMPORARY TABLESPACE TEMP
  PROFILE DEFAULT
  ACCOUNT UNLOCK;

GRANT RESOURCE TO B;
ALTER USER B DEFAULT ROLE NONE;

-- 2 System Privileges for B 
GRANT CREATE TABLE TO B;
GRANT CREATE PROCEDURE TO B;
GRANT CREATE SESSION TO B;
ALTER USER B QUOTA UNLIMITED ON USERS;


Login as User A and create the database links (To keep the example simple, I have simply let the database links refer to the local DB):
CREATE DATABASE LINK "DB1"
 CONNECT TO HR
 IDENTIFIED BY HR
 USING '(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = localhost) (PORT = 1521)) (CONNECT_DATA = (SERVER = dedicated) (SID=ORCL)))';

CREATE DATABASE LINK "DB2"
 CONNECT TO HR
 IDENTIFIED BY HR
 USING '(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = localhost) (PORT = 1521)) (CONNECT_DATA = (SERVER = dedicated) (SID=ORCL)))';

CREATE DATABASE LINK "DB3"
 CONNECT TO HR
 IDENTIFIED BY HR
 USING '(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = localhost) (PORT = 1521)) (CONNECT_DATA = (SERVER = dedicated) (SID=ORCL)))';


Login as User B and run the following commands:
DROP TABLE dbs;
DROP TABLE depstats;

CREATE TABLE dbs
(
  dblink    VARCHAR2 (100)
);

INSERT INTO dbs
     VALUES ('A.DB1');

INSERT INTO dbs
     VALUES ('A.DB2');

INSERT INTO dbs
     VALUES ('A.DB3');

CREATE TABLE depstats
(
  dblink           VARCHAR2 (100)
, department_id    VARCHAR2 (4)
, emps#            NUMBER (5)
, avg_sal          NUMBER (10, 2)
, max_sal          NUMBER (8, 2)
, refresh_date     DATE
);

CREATE OR REPLACE PROCEDURE refresh_deptstats
IS
BEGIN
  FOR r IN (SELECT dblink FROM dbs)
  LOOP
    EXECUTE IMMEDIATE 'INSERT INTO depstats (dblink
                           , department_id
                           , emps#
                           , avg_sal
                           , max_sal
                           , refresh_date)
        SELECT ''' || r.dblink || ''' as dblink
             , department_id
             , COUNT (employee_id) AS emps#
             , ROUND (AVG (salary)) AS avg_sal
             , MAX (salary) AS max_sal
             , SYSDATE
          FROM hr.employees@' || r.dblink || '   GROUP BY department_id';

    COMMIT;
  END LOOP;
END;
/

EXEC refresh_deptstats;

SELECT * FROM depstats;


The Procedure refresh_deptstats fails with
ORA-02019: connection description for remote database not found
Since there is no way to grant privileges on database links to other users, I don't know how to accomplish the task.

Chris Saxon
September 02, 2024 - 2:41 pm UTC

You can't schema-qualify database links. If you want to access a DB link owned by another user, make it a public link.

T.O.L.

J. Laurindo Chiappa, September 03, 2024 - 3:27 pm UTC

Just thinking loud, but what about something such like creating the dblink without providing username and password (see https://asktom.oracle.com/ords/f?p=100:11:::::P11_QUESTION_ID:9536128200346372995 ) and later the privilege of connecting impersonating the user implicit in the dblink (connect through) is given to the user who wants to access the dblink ? Could something like this work ?
Connor McDonald
September 04, 2024 - 2:21 am UTC

That helps with authentication but doesn't change the fact that you can't schema prefix the link. But yes, a public link with no user/pass at least ensures that you have to have an account on the target to let you gain access to the data.