J'ai deux bases de données Postgres différentes sur deux serveurs différents (l'un est en fait local). Similaire à cette question , je voudrais travailler avec les deux bases de données en même temps. Cependant, je ne peux pas trouver un moyen de le faire en utilisant psycopg2
.
Je pensais donc que j'avais probablement besoin de deux curseurs différents:
conn_local = psycopg2.connect(dbname='local_db', Host='localhost')
conn_remote = psycopg2.connect(dbname='remote_db', Host='some.other.server')
curs_local = conn_local.cursor()
curs_remote = conn_remote.cursor()
Mais comment puis-je adresser ces bases de données? Par exemple, lorsque j'essaye de joindre des données des deux tables:
curs_local.execute("""
CREATE TABLE local_db.public.newtable AS
SELECT remote_db.public.remotetable.rcolumn AS col_from_remote,
local_db.public.localtable.lcolumn AS col_from_local
FROM remote_db.public.remotetable, local_db.public.localtable""")
Il y aura une erreur dans le style de psycopg2.NotSupportedError: cross-database references are not implemented: "local_db.public.new_table"
. Le ATTACH TABLE
(comme décrit dans la solution ici ) n'existe apparemment pas dans Postgres/psycopg2.
Est-il possible de travailler avec plusieurs bases de données à la fois? Comment? Ou vais-je devoir copier (exporter/importer) les données de remote_db
à local_db
première?
Oui, il est possible de travailler avec plusieurs bases de données en même temps mais vous cherchez au mauvais endroit. psycopg2 n'est qu'une bibliothèque qui simplifie l'accès et la manipulation des données provenant de PostgreSQL, mais elle ne va pas bien au-delà de ce que vous pouvez faire avec psql. Ce que vous cherchez à faire, vous pouvez le résoudre au niveau de la base de données en utilisant Foreign Data Wrappers .
Cela devient plus compliqué dans votre définition de schéma mais apporte des tables distantes de l'hôte some.other.server
base de données remote_db
pour apparaître comme s'ils vivaient sur localhost
dans la base de données local_db
. Un exemple simple sur la façon de connecter les wrappers:
CREATE EXTENSION postgres_fdw;
CREATE SERVER some_remote_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (Host 'some.remote.server', port '5432', dbname 'remote_db');
CREATE USER MAPPING FOR local_user
SERVER some_remote_server
OPTIONS (user 'remote_user', password 'remote_user_password');
CREATE FOREIGN TABLE local_table_name (id int, value int)
SERVER some_remote_server
OPTIONS ( schema_name 'remote_schema_name', table_name 'remote_table_name');
Maintenant, localement, vous pouvez simplement exécuter
SELECT * from local_table_name
et la requête sera exécutée sur l'hôte distant. Il va sans dire que cela nécessite une connectivité entre les deux serveurs.
De même, si vous le devez vraiment, vous pouvez créer un serveur "distant" par rapport à l'hôte local et pointer vers une autre base de données locale pour les requêtes entre bases de données. Se sent sale mais c'est possible.
Comme l'a mentionné @a_horse_with_no_name, ce n'est pas très efficace. Si vous faites cela trop fréquemment, vous n'obtenez pas les performances les plus optimales et vous feriez mieux d'avoir de très bonnes raisons de garder vos bases de données séparées à ce stade.
PostgreSQL appelle des "schémas" ce que MySQL appelle des bases de données. Ne créez pas plusieurs bases de données avec l'intention de travailler ensemble. Cela dit, si vous avez besoin d'accéder à une base de données externe, le FDW PostgreSQL vous aidera
Comme je viens de l'apprendre de cette réponse , une approche alternative serait dblink
. Par exemple.:
SELECT *
FROM dblink('dbname=mydb', 'select rcol1, rcol2 from remote_db')
AS t1(rcol1 name, rcol2 text)