Czy można wykonywać zapytania między bazami danych za pomocą PostgreSQL?

143

Zgaduję, że odpowiedź brzmi „nie” na podstawie poniższego komunikatu o błędzie (i tego wyniku Google ), ale czy istnieje możliwość wykonania zapytania między bazami danych przy użyciu PostgreSQL?

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

Pracuję z niektórymi danymi, które są podzielone na dwie bazy danych, chociaż dane są naprawdę współdzielone między nimi (kolumny identyfikatorów użytkowników w jednej bazie danych pochodzą z userstabeli w drugiej bazie danych). Nie mam pojęcia, dlaczego są to dwie oddzielne bazy danych zamiast schematu, ale c'est la vie ...

matowe b
źródło

Odpowiedzi:

111

Uwaga: Jak sugerował oryginalny asker, jeśli konfigurujesz dwie bazy danych na tym samym komputerze, prawdopodobnie chcesz zamiast tego utworzyć dwa schematy - w takim przypadku nie potrzebujesz niczego specjalnego, aby przeszukiwać je.

postgres_fdw

Użyj postgres_fdw(obcego opakowania danych), aby połączyć się z tabelami w dowolnej bazie danych Postgres - lokalnej lub zdalnej.

Zwróć uwagę, że istnieją obce opakowania danych dla innych popularnych źródeł danych . W tej chwili tylko postgres_fdwi file_fdwsą częścią oficjalnej dystrybucji Postgres.

Dla wersji Postgres starszych niż 9.3

Wersje tak stare nie są już obsługiwane, ale jeśli trzeba to zrobić w instalacji Postgres sprzed 2013 roku, istnieje funkcja o nazwie dblink.

Nigdy go nie używałem, ale jest utrzymywany i rozpowszechniany z resztą PostgreSQL. Jeśli używasz wersji PostgreSQL dostarczonej z dystrybucją Linuksa, może być konieczne zainstalowanie pakietu o nazwie postgresql-contrib.

Neall
źródło
Musisz zainstalować postgresql-contribwcześniej dblink? Lub postgresql-contribzawiera dblink? I wtedy zapytanie OP będzie działało, czy musisz zapytać o to inaczej?
mpen
3
Z tego, co czytam, dblink nie obsługuje przypadku, w którym potrzebujesz zapytania obejmującego dwie bazy danych.
Paul Tomblin,
26

dblink () - wykonuje zapytanie w zdalnej bazie danych

dblink wykonuje zapytanie (zwykle SELECT, ale może to być dowolna instrukcja SQL zwracająca wiersze) w zdalnej bazie danych.

Gdy podane są dwa argumenty tekstowe, pierwszy z nich jest najpierw sprawdzany jako nazwa trwałego połączenia; jeśli zostanie znaleziony, polecenie jest wykonywane na tym połączeniu. Jeśli nie zostanie znaleziony, pierwszy argument jest traktowany jako ciąg informacji o połączeniu, tak jak w przypadku dblink_connect, a wskazane połączenie jest nawiązywane tylko na czas trwania tego polecenia.

jeden z dobrych przykładów:

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;

Uwaga: podaję te informacje do wykorzystania w przyszłości. Odniesienie

Manwal
źródło
21

Wpadłem na to, zanim doszedłem do tego samego wniosku o zapytaniach między bazami danych, co ty. Skończyło się na tym, że użyłem schematów do podzielenia obszaru tabel w ten sposób, że mogłem pogrupować tabele, ale nadal sprawdzałem je wszystkie.

stymulanty
źródło
17
Jeśli pochodzisz ze środowiska MySQL, to, co MySQL nazywa bazami danych, to tak naprawdę schematy (CREATE SCHEMA == CREATE DATABASE w MySQL), więc jeśli przenosisz coś z MySQL przy użyciu wielu baz danych, użyj schematów
MkV
10

Żeby dodać trochę więcej informacji.

Nie ma możliwości wysłania zapytania do bazy danych innej niż bieżąca. Ponieważ PostgreSQL ładuje katalogi systemowe specyficzne dla bazy danych, nie ma pewności, jak powinno zachowywać się zapytanie między bazami danych.

Contrib / dblink umożliwia wykonywanie zapytań między bazami danych przy użyciu wywołań funkcji. Oczywiście klient może również nawiązywać jednoczesne połączenia z różnymi bazami danych i łączyć wyniki po stronie klienta.

Często zadawane pytania dotyczące PostgreSQL

Esteban Küber
źródło
5
Te dodatkowe informacje mogą wprowadzać w błąd i mogą zniechęcać użytkowników do korzystania z powyższego rozwiązania.
johan855
5

Tak, możesz użyć DBlink (tylko postgresql) i DBI-Link (zezwala na zagraniczne zapytania między bazami danych) i TDS_LInk, który umożliwia uruchamianie zapytań na serwerze MS SQL.

Korzystałem już wcześniej z DB-Link i TDS-link z wielkim sukcesem.


źródło
2

Jeśli wydajność jest ważna, a większość zapytań jest tylko do odczytu, sugerowałbym replikację danych do innej bazy danych. Chociaż wydaje się to niepotrzebnym powielaniem danych, może pomóc, jeśli wymagane są indeksy.

Można to zrobić za pomocą prostych wyzwalaczy wstawiania, które z kolei wywołują dblink, aby zaktualizować inną kopię. Istnieją również pełne opcje replikacji (jak Slony), ale to nie na temat.

dpavlin
źródło
2

Jeśli ktoś potrzebuje bardziej zaangażowanego przykładu wykonywania zapytań między bazami danych, oto przykład, który czyści databasechangeloglocktabelę w każdej bazie danych, która ją posiada:

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
źródło
1

Sprawdziłem i próbowałem utworzyć relacje klucza obcego między 2 tabelami w 2 różnych bazach danych, używając zarówno dblink, jak i postgres_fdw, ale bez rezultatu.

Po przeczytaniu opinii innych ludzi na ten temat, na przykład tutaj i tutaj oraz w niektórych innych źródłach, wygląda na to, że obecnie nie można tego zrobić:

Dblink i postgres_fdw rzeczywiście umożliwić jednego do łączenia się i zapytania stoliki w innych bazach danych, co nie jest możliwe przy użyciu standardowych PostgreSQL, ale nie pozwalają na ustalenie kluczowych zagranicznych relacji między tabelami w różnych bazach danych.

Rocckk
źródło