Est-il possible d'effectuer des requêtes entre bases de données avec PostgreSQL?

144

Je vais deviner que la réponse est «non» en fonction du message d'erreur ci-dessous (et de ce résultat Google ), mais y a-t-il de toute façon pour effectuer une requête entre bases de données en utilisant PostgreSQL?

databaseA=# select * from databaseB.public.someTableName;
ERROR:  cross-database references are not implemented:
 "databaseB.public.someTableName"

Je travaille avec des données partitionnées sur deux bases de données bien que les données soient vraiment partagées entre les deux (les colonnes userid dans une base de données proviennent de la userstable de l'autre base de données). Je n'ai aucune idée pourquoi ce sont deux bases de données distinctes au lieu d'un schéma, mais c'est la vie ...

mat b
la source

Réponses:

111

Remarque: comme le demandeur d'origine l'a laissé entendre, si vous configurez deux bases de données sur la même machine, vous voudrez probablement créer deux schémas à la place - dans ce cas, vous n'avez besoin de rien de spécial pour les interroger.

postgres_fdw

Utilisez postgres_fdw(wrapper de données étrangères) pour vous connecter à des tables dans n'importe quelle base de données Postgres - locale ou distante.

Notez qu'il existe des wrappers de données étrangers pour d'autres sources de données populaires . Pour le moment, uniquement postgres_fdwet file_fdwfont partie de la distribution officielle de Postgres.

Pour les versions Postgres antérieures à la 9.3

Les versions aussi anciennes ne sont plus prises en charge, mais si vous devez le faire dans une installation Postgres antérieure à 2013, il existe une fonction appelée dblink .

Je ne l'ai jamais utilisé, mais il est maintenu et distribué avec le reste de PostgreSQL. Si vous utilisez la version de PostgreSQL fournie avec votre distribution Linux, vous devrez peut-être installer un package appelé postgresql-contrib.

Neall
la source
Besoin d'installer postgresql-contribavant dblink? Ou postgresql-contribcomprend dblink? Et puis la requête de l'OP fonctionnera, ou devez-vous l'interroger différemment?
mpen
3
D'après ce que je peux lire, dblink ne gère pas le cas où vous souhaitez une requête couvrant deux bases de données.
Paul Tomblin
27

dblink () - exécute une requête dans une base de données distante

dblink exécute une requête (généralement un SELECT, mais il peut s'agir de n'importe quelle instruction SQL qui renvoie des lignes) dans une base de données distante.

Lorsque deux arguments de texte sont donnés, le premier est d'abord recherché comme le nom d'une connexion persistante; s'il est trouvé, la commande est exécutée sur cette connexion. S'il n'est pas trouvé, le premier argument est traité comme une chaîne d'informations de connexion comme pour dblink_connect, et la connexion indiquée est établie uniquement pour la durée de cette commande.

l'un des bons exemples:

SELECT * 
FROM   table1 tb1 
LEFT   JOIN (
   SELECT *
   FROM   dblink('dbname=db2','SELECT id, code FROM table2')
   AS     tb2(id int, code text);
) AS tb2 ON tb2.column = tb1.column;

Remarque: je donne ces informations pour référence future. Réfrence

Manwal
la source
21

J'ai rencontré cela avant d'arriver à la même conclusion sur les requêtes croisées de bases de données que vous. Ce que j'ai fini par faire, c'était d'utiliser des schémas pour diviser l'espace table de cette façon, je pouvais garder les tables groupées tout en les interrogeant toutes.

stimms
la source
17
Si vous venez d'un environnement MySQL, ce que MySQL appelle des bases de données sont en réalité des schémas (CREATE SCHEMA == CREATE DATABASE in MySQL), donc si vous portez quelque chose de MySQL en utilisant plusieurs bases de données, utilisez des schémas
MkV
10

Juste pour ajouter un peu plus d'informations.

Il n'existe aucun moyen d'interroger une base de données autre que la base de données actuelle. Étant donné que PostgreSQL charge les catalogues système spécifiques aux bases de données, il n'est pas certain de savoir comment une requête entre bases de données devrait même se comporter.

contrib / dblink autorise les requêtes entre bases de données à l'aide d'appels de fonction. Bien entendu, un client peut également établir des connexions simultanées à différentes bases de données et fusionner les résultats côté client.

FAQ PostgreSQL

Esteban Küber
la source
5
Ces informations supplémentaires peuvent être trompeuses et peuvent décourager les utilisateurs d'utiliser la solution ci-dessus.
johan855
5

Oui, vous pouvez en utilisant DBlink (postgresql uniquement) et DBI-Link (autorise les requêtes de bases de données croisées étrangères) et TDS_LInk qui permet d'exécuter des requêtes sur le serveur MS SQL.

J'ai déjà utilisé DB-Link et TDS-link avec beaucoup de succès.


la source
2

Si les performances sont importantes et que la plupart des requêtes sont en lecture seule, je suggère de répliquer les données vers une autre base de données. Bien que cela semble être une duplication inutile des données, cela peut aider si des index sont nécessaires.

Cela peut être fait avec de simples déclencheurs d'insertion qui à leur tour appellent dblink pour mettre à jour une autre copie. Il existe également des options de réplication à part entière (comme Slony), mais c'est hors sujet.

dpavlin
la source
2

Si quelqu'un a besoin d'un exemple plus complexe sur la façon de faire des requêtes entre bases de données, voici un exemple qui nettoie la databasechangeloglocktable sur chaque base de données qui la contient:

CREATE EXTENSION IF NOT EXISTS dblink;

DO 
$$
DECLARE database_name TEXT;
DECLARE conn_template TEXT;
DECLARE conn_string TEXT;
DECLARE table_exists Boolean;
BEGIN
    conn_template = 'user=myuser password=mypass dbname=';

    FOR database_name IN
        SELECT datname FROM pg_database
        WHERE datistemplate = false
    LOOP
        conn_string = conn_template || database_name;

        table_exists = (select table_exists_ from dblink(conn_string, '(select Count(*) > 0 from information_schema.tables where table_name = ''databasechangeloglock'')') as (table_exists_ Boolean));
        IF table_exists THEN
            perform dblink_exec(conn_string, 'delete from databasechangeloglock');
        END IF;     
    END LOOP;

END
$$
Haroldo_OK
la source
1

J'ai vérifié et essayé de créer une relation de clé étrangère entre 2 tables dans 2 bases de données différentes en utilisant à la fois dblink et postgres_fdw mais sans résultat.

Après avoir lu les commentaires des autres personnes à ce sujet, par exemple ici et ici et dans d'autres sources, il semble qu'il n'y ait aucun moyen de le faire actuellement:

Les dblink et postgres_fdw permettent en effet de se connecter et d'interroger des tables dans d'autres bases de données, ce qui n'est pas possible avec le standard Postgres, mais ils ne permettent pas d'établir des relations de clé étrangère entre des tables dans différentes bases de données.

Rocckk
la source