Foreign tables
Overview
PostgreSQL partially implements the SQL/MED specification. It allows you to use regular SQL queries to access data that resides outside PostgreSQL. This data is called third-party data. To access it, follow the steps below:
-
Use a foreign data wrapper. A foreign data wrapper connects to external data sources and obtains data from them. The contrib extension included in the ADPG installation contains multiple foreign data wrappers. See Additional Supplied Modules for details. You can also use third-party data wrappers or write your own. See Writing a foreign data wrapper.
-
Define a foreign server object that encapsulates connection information for the corresponding foreign data wrapper. Use the CREATE SERVER command for this:
CREATE SERVER [ IF NOT EXISTS ] <server_name> [ TYPE '<server_type>' ] [ VERSION '<server_version>' ] FOREIGN DATA WRAPPER <fdw_name> [ OPTIONS ( <option 'value' [, ... ]> ) ]
Parameters of the CREATE SERVER commandIF NOT EXISTS
When this option is specified, PostgreSQL does not throw an error if a server with the specified name exists. There is no guarantee that the existing server matches the one that would be created
<server_name>
The name of a new foreign server. The server name must be unique within the database
<server_type>
An optional parameter that specifies a server type. It can be useful to foreign data wrappers
<server_version>
An optional parameter that specifies a server version. It can be useful to foreign data wrappers
<fdw_name>
A name of a foreign data wrapper that manages the foreign server
OPTIONS ( <option 'value' [, … ]> )
Specifies the server options. These options define the connection details, but the names and values are dependent on the specified foreign data wrapper
The user, who defines the server, becomes its owner. To create the server, the user should have the
USAGE
privilege on the specified foreign data wrapper. -
Access to remote data may require authentication to an external data source. Create a user mapping object to specify a user name and password that can be used for the authentication of a current PostgreSQL role. To do this, execute the CREATE USER MAPPING command that has the following syntax:
CREATE USER MAPPING [ IF NOT EXISTS ] FOR { <user_name> | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC } SERVER <server_name> [ OPTIONS ( <option 'value' [ , ... ]> ) ]
Parameters of the CREATE USER MAPPING commandIF NOT EXISTS
Do not throw an error if a mapping of the given user to the given foreign server already exists. There is no guarantee that the existing user mapping matches the one that would be created
<user_name>
Specifies the name of an existing user that is mapped to a foreign server.
CURRENT_ROLE
,CURRENT_USER
, andUSER
match the name of the current user. WhenPUBLIC
is specified, the public mapping is created that is used when no user-specific mapping is applicable<server_name>
Defines a name of an existing server for which the user mapping is created
OPTIONS ( <option 'value' [, … ]> )
Specifies the options for user mapping. The options typically define the actual remote user name and password. The allowed option names and values are specific to the used foreign data wrapper
The owner of a foreign server can create user mappings for that server for any user. A user also can create a user mapping for their own user name if the
USAGE
privilege on the server is granted to the user. -
Create one or more foreign tables that define the remote data structure. A foreign table does not store data on the PostgreSQL server, but you can execute queries on it as on a regular table. PostgreSQL utilizes a foreign data wrapper to fetch data from an external source or transmit data to this source in case of update commands.
Execute the CREATE FOREIGN TABLE command to define a foreign table:
CREATE FOREIGN TABLE [ IF NOT EXISTS ] <table_name> ( [ { <column_name> <data_type> [ COLLATE <collation> ] [ <column_constraint> [ ... ] ] | <table_constraint> } [, ... ] ] ) [ INHERITS ( <parent_table> [, ... ] ) ] SERVER <server_name> [ OPTIONS ( <option 'value'> [, ... ] ) ] CREATE FOREIGN TABLE [ IF NOT EXISTS ] <table_name> PARTITION OF <main_table> [ ( { <column_name> [ WITH OPTIONS ] [ <column_constraint> [ ... ] ] | <table_constraint> } [, ... ] ) ] { FOR VALUES <partition_bound_spec> | DEFAULT } SERVER <server_name> [ OPTIONS ( <option 'value' [, ... ]> ) ]
Parameters of the CREATE FOREIGN TABLE commandIF NOT EXISTS
When this option is specified, PostgreSQL does not throw an error if a relation with the specified name is in the database. There is no guarantee that the existing relation matches the one that would be created
<table_name>
The name of a new table. Can be schema-qualified (
<schema_name>.<table_name>
)<column_name>
The name of a column to be created in the new table
<data_type>
The column data type. This can include array specifiers. For more information on supported data types, refer to Data types
COLLATE <collation>
Defines the column collation. If this setting is not specified, PostgreSQL uses the column data type’s default collation
INHERITS ( <parent_table> [, … ] )
Specifies a list of tables from which the new table automatically inherits all columns. Parent tables can be ordinary tables or foreign tables. See Inheritance
PARTITION OF <parent_table>
Creates a foreign table as a partition of the given parent table with specified partition bound values. See Partitioning for more information on partitioning options. Note that it is not allowed to create the foreign table as a partition of the parent table if there are
UNIQUE
indexes on the parent table<column_constraint>
Defines column constraints that are described in the Use constraints section
<table_constraint>
Specifies table constraints that are described in the Use constraints section
<server_name>
Defines the name of an existing foreign server to use for a foreign table
OPTIONS ( <option 'value' [, …]> )
Specifies options associated with a new foreign table or one of its columns. The allowed option names and values are specific to each foreign data wrapper
Alternatively, you can import the entire foreign schema. To do this, execute the IMPORT FOREIGN SCHEMA command. It creates foreign tables that represent tables existing on a foreign server. PostgreSQL creates foreign tables with column definitions and options that match the remote tables. The user, who executes the
IMPORT FOREIGN SCHEMA
command, is the owner of new foreign tables. The command has the following syntax:IMPORT FOREIGN SCHEMA <remote_schema> [ { LIMIT TO | EXCEPT } ( <table_name> [, ...] ) ] FROM SERVER <server_name> INTO <local_schema> [ OPTIONS ( <option 'value' [, ... ]> ) ]
Parameters of the IMPORT FOREIGN SCHEMA command<remote_schema>
Defines a remote schema to import from. What exactly a remote schema is depends on the used foreign data wrapper
LIMIT TO ( <table_name [, …]> )
Imports only foreign tables matching one of the given table names. Other tables existing in the foreign schema are ignored
EXCEPT ( <table_name [, …]> )
Excludes specified foreign tables from the import. All tables existing in the foreign schema are imported except the ones listed in this clause
<server_name>
Defines the foreign server to import from
<local_schema>
Sets the schema in which the imported foreign tables are created
OPTIONS ( <option 'value' [, …]> )
Specifies options to be used during the import. The allowed option names and values are specific to each foreign data wrapper
The list of imported tables can be limited to a specified subset, or specific tables can be excluded from import. The target local schema must already exist.
To run
IMPORT FOREIGN SCHEMA
, the user must have theUSAGE
privilege on the foreign server and theCREATE
privilege on the target local schema.
To display foreign tables from the current database, use the following query:
SELECT * FROM information_schema.foreign_tables;
Examples
The contrib extension contains the following data wrappers:
-
postgres_fdw
— can be used to access data stored in external PostgreSQL servers. See postgres_fdw. -
file_fdw
— can be used to access data files in the server file system, or to execute programs on the server and read their output. See file_fdw.
You can find examples of using these data wrappers below.
Access data stored in external PostgreSQL servers
Assume that an external PostgreSQL server contains the books
and authors
tables in the books_store
database.
The authors
table is created as follows:
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
To access data from this server, follow the steps below:
-
Use an existing role on a remote server or create a new user and grant appropriate permissions. For example:
CREATE ROLE user1 WITH PASSWORD 'password' LOGIN; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO user1; GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO user1;
-
Since ADPG includes the contrib extension, you just need to execute the
CREATE EXTENSION
command to use thepostgres_fdw
data wrapper on the local server:CREATE EXTENSION postgres_fdw;
-
Create a foreign server in your local database. The following code creates a server that connects to the
books_store
database located on the10.92.6.225
host:CREATE SERVER server1 FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '10.92.6.225', port '5432', dbname 'books_store');
If the remote server uses the standard port, the
port
option can be omitted. -
Define user mapping. Pass the credentials of the user you created on the remote server as options. The following code creates user mapping for the
postgres
user from the local server:CREATE USER MAPPING FOR postgres SERVER server1 OPTIONS (user 'user1', password 'password');
-
Create a foreign table on the local server:
CREATE FOREIGN TABLE authors ( id int, name VARCHAR(100) NOT NULL ) SERVER server1;
Check the result:
SELECT * FROM authors;
The output:
id | name ----+--------------------- 1 | Virginia Woolf 2 | Harper Lee 3 | F. Scott Fitzgerald 4 | J.R.R. Tolkien 5 | George Orwell
Alternatively, import the entire scheme:
CREATE SCHEMA schema1; IMPORT FOREIGN SCHEMA public from SERVER server1 into schema1;
Display the existing foreign tables to check the result:
SELECT * FROM information_schema.foreign_tables;
The result:
foreign_table_catalog | foreign_table_schema | foreign_table_name | foreign_server_catalog | foreign_server_name -----------------------+----------------------+--------------------+------------------------+--------------------- postgres | public | authors | postgres | server1 postgres | schema1 | authors | postgres | server1 postgres | schema1 | books | postgres | server1
The books
and authors
tables have been imported into shema1
.
Access data files in the server file system
For example, we have the following books.csv file:
1,Mrs. Dalloway,1,1925,novel 2,To the Lighthouse,1,1927,novel 3,To Kill a Mockingbird,2,1960,novel 4,The Lord of the Rings,4,1955,fantasy 5,1984,5,1949,sci-fi
We need to use SQL to access the data from this file. To accomplish this task, perform the following steps:
-
Execute the
CREATE EXTENSION
command to use thefile_fdw
data wrapper:CREATE EXTENSION file_fdw;
-
Define a foreign server:
CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;
-
Create a foreign table. Its structure should match the file structure. Pass the file path and file format in the
OPTIONS
clause:CREATE FOREIGN TABLE foreign_books ( id INT, title VARCHAR(255), author_id INT, public_year INT, genre VARCHAR(50) ) SERVER file_server OPTIONS ( filename '/var/lib/pgsql/books.csv', format 'csv' );
Now you can use SQL commands to access data, for example:
SELECT * FROM foreign_books;
The result:
id | title | author_id | public_year | genre ----+-----------------------+-----------+-------------+--------- 1 | Mrs. Dalloway | 1 | 1925 | novel 2 | To the Lighthouse | 1 | 1927 | novel 3 | To Kill a Mockingbird | 2 | 1960 | novel 4 | The Lord of the Rings | 4 | 1955 | fantasy 5 | 1984 | 5 | 1949 | sci-fi