È possibile eseguire query tra database con PostgreSQL?


144

Immagino che la risposta sia "no" in base al messaggio di errore riportato di seguito (e questo risultato di Google ), ma esiste comunque una query tra database utilizzando PostgreSQL?

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

Sto lavorando con alcuni dati che sono partizionati su due database sebbene i dati siano realmente condivisi tra i due (le colonne userid in un database provengono dal users tabella nell'altro database). Non ho idea del perché si tratti di due database separati invece dello schema, ma c'est la vie ...

Risposte:


111

Nota: come suggeriva il richiedente originale, se si stanno configurando due database sulla stessa macchina, probabilmente si vogliono fare due schemi , in tal caso non è necessario nulla di speciale per interrogarli.

postgres_fdw

Uso postgres_fdw (wrapper di dati esterno) per connetterti alle tabelle di qualsiasi database Postgres - locale o remoto.

Si noti che esistono wrapper di dati esterni per altre origini dati popolari . In questo momento, solo postgres_fdwefile_fdw fanno parte della distribuzione ufficiale di Postgres.

Per le versioni Postgres precedenti alla 9.3

Le versioni precedenti non sono più supportate, ma se è necessario eseguire questa operazione in un'installazione Postgres precedente al 2013, esiste una funzione chiamata dblink .

Non l'ho mai usato, ma è gestito e distribuito con il resto di PostgreSQL. Se stai usando la versione di PostgreSQL fornita con la tua distribuzione Linux, potresti aver bisogno di installare un pacchetto chiamato postgresql-contrib.


Devi installare postgresql-contribprima dblink? O postgresql-contribinclude dblink? E poi la query del PO funzionerà o devi interrogarla in modo diverso?
mpen

3
Da quello che posso leggere, dblink non gestisce il caso in cui si desidera una query che si estende su due database.
Paul Tomblin,

26

dblink () : esegue una query in un database remoto

dblink esegue una query (in genere un SELECT, ma può essere qualsiasi istruzione SQL che restituisce righe) in un database remoto.

Quando vengono forniti due argomenti di testo, il primo viene prima cercato come nome di una connessione persistente; se trovato, il comando viene eseguito su quella connessione. Se non trovato, il primo argomento viene trattato come una stringa di informazioni di connessione come per dblink_connect e la connessione indicata viene effettuata solo per la durata di questo comando.

uno dei buoni esempi:

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;

Nota: sto fornendo queste informazioni per riferimento futuro. refrence


21

Mi sono imbattuto in questo prima che arrivassi alla stessa conclusione sulle tue domande tra database. Quello che ho finito per fare è stato usare gli schemi per dividere il tablespace in modo da poter tenere raggruppati i tavoli ma comunque interrogarli tutti.


17
Se provieni da un ambiente MySQL, quelli che MySQL chiama database sono in realtà schemi (CREATE SCHEMA == CREATE DATABASE in MySQL), quindi se porti qualcosa da MySQL usando database multipli, usa gli schemi
MkV

10

Solo per aggiungere un po 'più di informazioni.

Non è possibile eseguire query su un database diverso da quello corrente. Poiché PostgreSQL carica cataloghi di sistema specifici del database, non è sicuro come dovrebbe comportarsi una query tra database.

contrib / dblink consente query tra database utilizzando chiamate di funzione. Naturalmente, un client può anche effettuare connessioni simultanee a database diversi e unire i risultati sul lato client.

Domande frequenti su PostgreSQL


5
Queste informazioni aggiuntive possono essere fuorvianti e possono scoraggiare gli utenti a utilizzare la soluzione di cui sopra.
johan855,

5

Sì, è possibile utilizzando DBlink (solo postgresql) e DBI-Link (consente query con database incrociati stranieri) e TDS_LInk che consente l'esecuzione di query su MS SQL Server.

Ho usato DB-Link e TDS-link prima con grande successo.


2

Se le prestazioni sono importanti e la maggior parte delle query sono di sola lettura, suggerirei di replicare i dati su un altro database. Anche se questa sembra una duplicazione non necessaria di dati, potrebbe essere utile se sono richiesti indici.

Questo può essere fatto con semplici trigger di inserimento che a loro volta chiamano dblink per aggiornare un'altra copia. Ci sono anche opzioni di replica complete (come Slony) ma è fuori tema.


2

Nel caso in cui qualcuno abbia bisogno di un esempio più coinvolto su come eseguire query tra database, ecco un esempio che pulisce la databasechangeloglocktabella su ogni database che lo ha:

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
$$

1

Ho controllato e cercato di creare relazioni di chiave esterna tra 2 tabelle in 2 database diversi utilizzando sia dblink che postgres_fdw ma senza risultati.

Dopo aver letto il feedback degli altri su questo, ad esempio qui e qui e in alcune altre fonti sembra che al momento non sia possibile farlo:

Il dblink e postgres_fdw anzi consentire uno per connettersi e interrogare le tabelle in altri database, che non è possibile con le Postgres standard, ma non consentono di stabilire relazioni di chiave esterna tra le tabelle di database diversi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.