Возможно ли выполнять кросс-запросы к базе данных с PostgreSQL?

144

Я собираюсь догадаться, что ответ «нет» на основании приведенного ниже сообщения об ошибке (и это результат Google ), но есть ли способ выполнить кросс-запрос базы данных с использованием PostgreSQL?

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

Я работаю с некоторыми данными, которые распределены по двум базам данных, хотя данные действительно распределяются между ними (столбцы идентификаторов пользователей в одной базе данных берутся из usersтаблицы в другой базе данных). Я понятия не имею, почему это две отдельные базы данных, а не схема, но c'est la vie ...

Мэтт Б
источник

Ответы:

111

Примечание. Как и предполагал первоначальный аскер, если вы настраиваете две базы данных на одном компьютере, вы, вероятно, захотите создать вместо них две схемы - в этом случае вам не нужно ничего особенного для запроса к ним.

postgres_fdw

Используйте postgres_fdw(сторонний упаковщик данных) для подключения к таблицам в любой базе данных Postgres - локальной или удаленной.

Обратите внимание, что существуют сторонние обертки данных для других популярных источников данных . На данный момент только postgres_fdwи file_fdwявляются частью официального дистрибутива Postgres.

Для версий Postgres до 9.3

Версии этого старого больше не поддерживаются, но если вам нужно сделать это при установке Postgres до 2013 года, есть функция с именем dblink.

Я никогда не использовал его, но он поддерживается и распространяется с остальной частью PostgreSQL. Если вы используете версию PostgreSQL, поставляемую с вашим дистрибутивом Linux, вам может потребоваться установить пакет с именем postgresql-contrib.

Neall
источник
Нужно установить postgresql-contribраньше dblink? Или postgresql-contribвключает dblink? И тогда запрос OP будет работать, или вам нужно запросить его по-другому?
mpen
3
Из того, что я могу прочитать, dblink не обрабатывает случай, когда вы хотите запрос, который охватывает две базы данных.
Пол Томблин
27

dblink () - выполняет запрос в удаленной базе данных

dblink выполняет запрос (обычно SELECT, но это может быть любой оператор SQL, который возвращает строки) в удаленной базе данных.

Когда заданы два текстовых аргумента, первый из них сначала ищется как имя постоянного соединения; если найдено, команда выполняется для этого соединения. Если не найдено, первый аргумент обрабатывается как строка информации о соединении, как для dblink_connect, и указанное соединение устанавливается только на время выполнения этой команды.

один из хороших примеров:

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;

Примечание: я даю эту информацию для дальнейшего использования. Refrence

оборота Манвал
источник
21

Я столкнулся с этим до того, как пришел к тому же выводу о кросс-запросах к базе данных, что и вы. В итоге я использовал схемы для разделения табличного пространства таким образом, чтобы я мог сохранять таблицы сгруппированными, но при этом запрашивать их все.

stimms
источник
17
Если вы пришли из среды MySQL, то, что MySQL называет базами данных, - это действительно схемы (CREATE SCHEMA == CREATE DATABASE в MySQL), поэтому, если вы переносите что-то из MySQL с использованием нескольких баз данных, используйте схемы
MkV
10

Просто чтобы добавить немного больше информации.

Нет другого способа сделать запрос к базе данных, кроме текущей. Поскольку PostgreSQL загружает специфичные для базы данных системные каталоги, неясно, как должен вести себя кросс-запрос базы данных.

contrib / dblink позволяет выполнять запросы между базами данных, используя вызовы функций. Конечно, клиент также может одновременно устанавливать соединения с различными базами данных и объединять результаты на стороне клиента.

PostgreSQL FAQ

Эстебан Кюбер
источник
5
Эта дополнительная информация может вводить в заблуждение и может отговорить пользователей использовать вышеуказанное решение.
johan855
5

Да, вы можете использовать DBlink (только postgresql) и DBI-Link (разрешает внешние кросс-запросы к базам данных) и TDS_LInk, который позволяет выполнять запросы к серверу MS SQL.

Я использовал DB-Link и TDS-link раньше с большим успехом.


источник
2

Если важна производительность и большинство запросов доступны только для чтения, я бы предложил реплицировать данные в другую базу данных. Хотя это кажется ненужным дублированием данных, это может помочь, если требуются индексы.

Это можно сделать с помощью простых триггеров вставки, которые в свою очередь вызывают dblink для обновления другой копии. Есть также полнофункциональные варианты репликации (например, Slony), но это не по теме.

dpavlin
источник
2

В случае, если кому-то нужен более сложный пример выполнения запросов между базами данных, вот пример, который очищает databasechangeloglockтаблицу в каждой базе данных, в которой он есть:

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
источник
1

Я проверил и попытался создать отношения внешнего ключа между 2 таблицами в 2 разных базах данных, используя dblink и postgres_fdw, но безрезультатно .

Прочитав отзывы других людей по этому поводу, например, здесь и здесь, и в некоторых других источниках, похоже, что в настоящее время нет способа сделать это:

DBLink и postgres_fdw действительно позволяют подключиться к и запросам к таблицам других баз данных, что невозможно со стандартным Postgres, но они не позволяют установить внешние отношения ключевых между таблицами в различных базах данных.

Rocckk
источник