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

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

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

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

Ответ 1

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

Обновление с 9.3

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

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

Оригинальный ответ для pre-9.3

Эта функция не входит в стандартную установку PostgreSQL по умолчанию, но вы можете ее добавить. Она называется dblink.

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

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

Часто задаваемые вопросы PostgreSQL

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

select
 uuid_generate_v4() as "j"
,"x"."i"
, 1 as "t"
,'territory' as "s"
,"j"."key" as "k"
,"j"."value" as "v"
,true as "a"
from ( select "x".rowguid as "i", row_to_json(x) "j" from adventureworks.salesterritory "x" ) "x" CROSS JOIN LATERAL json_each(x."j") AS "j"
where "j"."key" not in ('rowguid', 'modifieddate', 'territoryid')

Ответ 8

В случае, если кому-то нужен более сложный пример того, как выполнять запросы между базами данных, вот пример, который очищает таблицу 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
$$

Ответ 9

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

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

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