Steps to Setup Database Link in PostgreSQL

Database Link in PostgreSQL enables a database user to access a table present on a different PostgreSQL cluster. It provides a functionality in PostgreSQL similar to that of DB Link in Oracle, Linked Server in SQL Server and Federated Table in MySQL. In previous post we saw How to Setup foreign data wrapper (postgres_fdw) Click here to read more. In this post we will see Steps to Setup DB Link in PostgreSQL.

For this demonstration, we’ll use the databases local_db and remote_db. We will access a table employee in remote_db from local_db through DB LINK.

Below are the high-level steps we will follow to set up DB Link
1. Setup Remote DB & pg_hba.conf
2. Create the DBLink Extension
3. Create the Foreign Server
4. Create User Mapping
5. Grant the Local User Access to the Foreign Server
6. Establish connection

Below are setup details and the same will be used in this demonstration.

Sr. No.DB NameUser NameHostnameIPPort

Step 1. Setup Remote DB & pg_hba.conf: In this step, we will create Database remote_db & User fdw_user. DB remote_db will be used in a later step to create a Foreign Server and user fdw_user will be used in a later step to Create User Mapping. Make sure to update file pg_hba.conf to allow PostgreSQL DB connection from Server: test-machine01. We have added the line “host all all scram-sha-256” as we are using the ” ” as a subnet.

psql (13.2)
Type "help" for help.
postgres=# create database remote_db;
postgres=# CREATE USER fdw_user WITH ENCRYPTED PASSWORD 'secret';
postgres=# \du+
                                          List of roles
 Role name |                         Attributes                         | Member of | Description
 user_test   | Superuser                                                  | {}        |
 fdw_user  |                                                            | {}        |
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}        |
 repluser  | Replication                                                | {}        |
postgres=# \q
[postgres@test-machine02]psql -h test-machine02 -U fdw_user remote_db
Password for user fdw_user:
psql (13.2)
Type "help" for help.
remote_db=> create table employee (id int, first_name varchar(20), last_name varchar(20));
remote_db=> insert into employee values (1,'jobin','augustine'),(2,'avinash','vallarapu'),(3,'fernando','camargos');
remote_db=> \dt employee
          List of relations
 Schema |   Name   | Type  |  Owner
 public | employee | table | fdw_user
(1 row)
remote_db=> select count(*) from employee;
(1 row)
[postgres@test-machine02]cat pg_hba.conf
# IPv4 local connections:
host    all             all               scram-sha-256
host    all             all           scram-sha-256

Step 2. Create the DBLink Extension: Use psql command to create an extension to create the dblink extension. If you receive the error “ERROR: could not open extension control file dblink.control: No such file or directory“. You need to install postgresql13-contrib package. Use OS yum install command to install the missing PostgreSQL package. Once the package is installed try to create a dblink extension again. Please note all below commands we are executing in DB: local_db as we want to avoid using default postgres DB.

[root@test-machine01 ~]# su - postgres
Last login: Fri Oct  1 12:24:24 +03 2021 on pts/0
[postgres@test-machine01] psql local_db
psql (9.2.24, server 13.4)
WARNING: psql version 9.2, server version 13.0.
         Some psql features might not work.
Type "help" for help.

local_db=# create extension dblink;
ERROR:  could not open extension control file "/usr/pgsql-13/share/extension/dblink.control": No such file or directory

[root@test-machine01 extension]# yum install postgresql13-contrib
Loaded plugins: langpacks, ulninfo
Dependencies Resolved
 Package                                          Arch                               Version                                        Repository                          Size
 postgresql13-contrib                             x86_64                             13.4-1PGDG.rhel7                               pgdg13                             609 k
Updating for dependencies:
 postgresql13                                     x86_64                             13.4-1PGDG.rhel7                               pgdg13                             1.4 M
 postgresql13-libs                                x86_64                             13.4-1PGDG.rhel7                               pgdg13                             381 k
 postgresql13-server                              x86_64                             13.4-1PGDG.rhel7                               pgdg13                             5.4 M
Transaction Summary
Install  1 Package
Upgrade             ( 3 Dependent packages)
  Verifying  : postgresql13-13.1-1PGDG.rhel7.x86_64                                                                                                                      5/7
  Verifying  : postgresql13-libs-13.1-1PGDG.rhel7.x86_64                                                                                                                 6/7
  Verifying  : postgresql13-server-13.1-1PGDG.rhel7.x86_64                                                                                                               7/7
  postgresql13-contrib.x86_64 0:13.4-1PGDG.rhel7
Dependency Updated:
  postgresql13.x86_64 0:13.4-1PGDG.rhel7               postgresql13-libs.x86_64 0:13.4-1PGDG.rhel7               postgresql13-server.x86_64 0:13.4-1PGDG.rhel7
[root@test-machine01 extension]#

local_db=# create extension dblink;
local_db=# \dx
                                    List of installed extensions
     Name     | Version |   Schema   |                         Description
 dblink       | 1.2     | public     | connect to other PostgreSQL databases from within a database
 plpgsql      | 1.0     | pg_catalog | PL/pgSQL procedural language
 postgres_fdw | 1.0     | public     | foreign-data wrapper for remote PostgreSQL servers
(3 rows)

local_db=#  select * from pg_extension;
  oid  |   extname    | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition
 14161 | plpgsql      |       10 |           11 | f              | 1.0        |           |
 26435 | postgres_fdw |       10 |         2200 | t              | 1.0        |           |
 26444 | dblink       |       10 |         2200 | t              | 1.2        |           |
(3 rows)


Step 3. Create the Foreign Server: Now we can create a server definition. This foreign server is created using the connection details of the remote server running on host “test-machine02“. Let’s name the foreign server as “testmachine02_dblink “. Use \des to list foreign servers or query view pg_foreign_server.

local_db=# create server testmachine02_dblink foreign data wrapper dblink_fdw options (dbname 'remote_db', host 'test-machine02', port '5432');
local_db=#  \des+
                                                                        List of foreign servers
         Name         |  Owner   | Foreign-data wrapper |  Access privileges  | Type | Version |                       FDW Options                        | Description
 testmachine02_dblink | postgres | dblink_fdw           |                     |      |         | (dbname 'remote_db', host 'test-machine02', port '5432') |
 testmachine02_fdw    | postgres | postgres_fdw         | postgres=U/postgres+|      |         | (dbname 'remote_db', host 'test-machine02', port '5432') |
                      |          |                      | app_user=U/postgres |      |         |                                                          |
(2 rows)

local_db=# select * from pg_foreign_server;
  oid  |       srvname        | srvowner | srvfdw | srvtype | srvversion |                  srvacl                   |                    srvoptions
 26439 | testmachine02_fdw    |       10 |  26438 |         |            | {postgres=U/postgres,app_user=U/postgres} | {dbname=remote_db,host=test-machine02,port=5432}
 26492 | testmachine02_dblink |       10 |  26489 |         |            |                                           | {dbname=remote_db,host=test-machine02,port=5432}
(2 rows)


Step 4. Create User Mapping: Create a mapping on the local databaselocal_db user app_user to target database: remot_db user fdw_user.

local_db=# create user mapping for app_user server testmachine02_dblink options (user 'fdw_user', password 'secret');
local_db=# select * from pg_user_mappings;
 umid  | srvid |       srvname        | umuser | usename  |            umoptions
 26440 | 26439 | testmachine02_fdw    |  26421 | app_user | {user=fdw_user,password=secret}
 26493 | 26492 | testmachine02_dblink |  26421 | app_user | {user=fdw_user,password=secret}
(2 rows)


Step 5. Grant the Local User Access to the Foreign Server: Grant our local user app_user access to the foreign server testmachine02_dblink. Without the below permission, you will receive the error “ERROR: permission denied for foreign server testmachine02_dblink” if you try to create a connection as we are doing in Step 6.

local_db=# grant usage on foreign server testmachine02_dblink to app_user;

Step 6. Establish connection: Establish a connection to the foreign server using the dblink_connect() function. Once the connection is established try to access Table: employee from remote_db.

local_db=# \quit
[postgres@test-machine01]  psql -h test-machine01 -U app_user local_db
Password for user app_user:
psql (9.2.24, server 13.4)
WARNING: psql version 9.2, server version 13.0.
         Some psql features might not work.
Type "help" for help.

local_db=> select dblink_connect('conn_dblink','testmachine02_dblink');
(1 row)

local_db=> select * from dblink ('conn_dblink','select * from employee') as test_dblink (id int, first_name varchar(20), last_name varchar(20));
 id | first_name | last_name
  1 | jobin      | augustine
  2 | avinash    | vallarapu
  3 | fernando   | camargos
(3 rows)


This document is just for learning purpose and always validate in the LAB environment first before applying in the LIVE environment.

Hope so you like this article!
Please share your valuable feedback/comments/subscribe and follow us below and don’t forget to click on the bell icon to get the most recent update. 
Click here to understand more about our pursuit.

Related Articles


How useful was this post?

Click on a star to rate it!

Average rating / 5. Vote count:

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Jamsher Khan

Hello and welcome to DBsGuru,I’m Jamsher Khan working as Senior Oracle DBA based in KSA-Jeddah, I have working experience in Oracle DBA, SQL Server, MySql, PostgreSQL, Linux, Golden Gate, ODA.Thanks for the visits!Share Learn Grow!