Kann datenbankübergreifende Abfragen mit PostgreSQL durchgeführt werden?

143

Ich gehe davon aus, dass die Antwort aufgrund der folgenden Fehlermeldung (und dieses Google-Ergebnisses ) "Nein" lautet. Gibt es dennoch eine Möglichkeit, eine datenbankübergreifende Abfrage mit PostgreSQL durchzuführen?

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

Ich arbeite mit einigen Daten, die auf zwei Datenbanken aufgeteilt sind, obwohl die Daten tatsächlich zwischen den beiden geteilt werden (Benutzer-ID-Spalten in einer Datenbank stammen aus der usersTabelle in der anderen Datenbank). Ich habe keine Ahnung, warum dies zwei separate Datenbanken anstelle von Schema sind, aber c'est la vie ...

matt b
quelle

Antworten:

111

Hinweis: Wie der ursprüngliche Fragesteller angedeutet hat, möchten Sie beim Einrichten von zwei Datenbanken auf demselben Computer wahrscheinlich stattdessen zwei Schemas erstellen. In diesem Fall benötigen Sie keine speziellen Abfragen, um sie abzufragen.

postgres_fdw

Verwenden Sie postgres_fdw(Fremddaten-Wrapper), um eine Verbindung zu Tabellen in einer beliebigen Postgres-Datenbank herzustellen - lokal oder remote.

Beachten Sie, dass es fremde Daten-Wrapper für andere gängige Datenquellen gibt . Derzeit nur postgres_fdwund file_fdwsind Teil der offiziellen Postgres-Distribution.

Für Postgres-Versionen vor 9.3

Versionen, die so alt sind, werden nicht mehr unterstützt. Wenn Sie dies jedoch in einer Postgres-Installation vor 2013 tun müssen, wird eine Funktion namens aufgerufen dblink.

Ich habe es nie benutzt, aber es wird mit dem Rest von PostgreSQL gepflegt und verteilt. Wenn Sie die Version von PostgreSQL verwenden, die mit Ihrer Linux-Distribution geliefert wurde, müssen Sie möglicherweise ein Paket namens postgresql-contrib installieren.

Neall
quelle
Müssen Sie postgresql-contribvorher installieren dblink? Oder postgresql-contribbeinhaltet dblink? Und dann funktioniert die Abfrage des OP, oder müssen Sie sie anders abfragen?
Mpen
3
Nach allem, was ich lesen kann, behandelt dblink nicht den Fall, dass Sie eine Abfrage wünschen, die zwei Datenbanken umfasst.
Paul Tomblin
26

dblink () - führt eine Abfrage in einer entfernten Datenbank aus

dblink führt eine Abfrage (normalerweise SELECT, aber es kann sich um eine beliebige SQL-Anweisung handeln, die Zeilen zurückgibt) in einer entfernten Datenbank aus.

Wenn zwei Textargumente angegeben werden, wird das erste zuerst als Name einer dauerhaften Verbindung nachgeschlagen. Wenn gefunden, wird der Befehl für diese Verbindung ausgeführt. Wenn es nicht gefunden wird, wird das erste Argument wie für dblink_connect als Verbindungsinfozeichenfolge behandelt, und die angegebene Verbindung wird nur für die Dauer dieses Befehls hergestellt.

eines der guten Beispiele:

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;

Hinweis: Ich gebe diese Informationen zum späteren Nachschlagen. Erfrischung

Manwal
quelle
21

Ich bin darauf gestoßen, bevor ich zu dem gleichen Schluss über datenbankübergreifende Abfragen gekommen bin wie Sie. Am Ende habe ich Schemata verwendet, um den Tabellenbereich so aufzuteilen, dass ich die Tabellen gruppieren und trotzdem alle abfragen konnte.

stimms
quelle
16
Wenn Sie aus einer MySQL-Umgebung kommen, sind die von MySQL als Datenbanken bezeichneten Datenbanken wirklich Schemata (CREATE SCHEMA == CREATE DATABASE in MySQL). Wenn Sie also etwas aus MySQL mithilfe mehrerer Datenbanken
portieren
10

Nur um ein bisschen mehr Informationen hinzuzufügen.

Es gibt keine andere Möglichkeit, eine andere Datenbank als die aktuelle abzufragen. Da PostgreSQL datenbankspezifische Systemkataloge lädt, ist es ungewiss, wie sich eine datenbankübergreifende Abfrage überhaupt verhalten soll.

Contrib / Dblink ermöglicht datenbankübergreifende Abfragen mithilfe von Funktionsaufrufen. Natürlich kann ein Client auch gleichzeitig Verbindungen zu verschiedenen Datenbanken herstellen und die Ergebnisse auf der Clientseite zusammenführen.

PostgreSQL FAQ

Esteban Küber
quelle
5
Diese zusätzlichen Informationen können irreführend sein und Benutzer davon abhalten, die oben genannte Lösung zu verwenden.
Johan855
5

Ja, Sie können DBlink (nur postgresql) und DBI-Link (ermöglicht datenbankübergreifende Fremdabfragen) sowie TDS_LInk verwenden, mit dem Abfragen für MS SQL Server ausgeführt werden können.

Ich habe DB-Link und TDS-Link bereits mit großem Erfolg verwendet.


quelle
2

Wenn die Leistung wichtig ist und die meisten Abfragen schreibgeschützt sind, würde ich empfehlen, Daten in eine andere Datenbank zu replizieren. Dies scheint zwar eine unnötige Duplizierung von Daten zu sein, kann jedoch hilfreich sein, wenn Indizes erforderlich sind.

Dies kann mit einfachen Triggern beim Einfügen erfolgen, die wiederum dblink aufrufen, um eine weitere Kopie zu aktualisieren. Es gibt auch vollständige Replikationsoptionen (wie Slony), aber das ist kein Thema.

dpavlin
quelle
2

Falls jemand ein beteiligtes Beispiel auf benötigt , wie Cross-Datenbank - Abfragen zu tun, hier ist ein Beispiel , das aufräumt der databasechangeloglockTabelle auf jeder Datenbank , die es hat:

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
quelle
1

Ich habe überprüft und versucht, eine Fremdschlüsselbeziehung zwischen 2 Tabellen in 2 verschiedenen Datenbanken mit dblink und postgres_fdw zu erstellen, aber ohne Ergebnis.

Nachdem ich das Feedback der anderen Leute dazu gelesen habe, zum Beispiel hier und hier und in einigen anderen Quellen, sieht es so aus, als gäbe es derzeit keine Möglichkeit, dies zu tun:

Mit dblink und postgres_fdw kann man zwar eine Verbindung zu Tabellen in anderen Datenbanken herstellen und diese abfragen, was mit den Standard-Postgres nicht möglich ist, aber es ist nicht möglich, Fremdschlüsselbeziehungen zwischen Tabellen in verschiedenen Datenbanken herzustellen.

Rocckk
quelle