Чи можливо виконувати запити міжбазових даних за допомогою PostgreSQL?


143

Я буду здогадуватися, що відповідь "ні" на основі наведеного нижче повідомлення про помилку (і цього результату 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.


Потрібно встановити postgresql-contribраніше dblink? Або postgresql-contribвключає dblink? І тоді запит ОП буде спрацьовувати, чи потрібно його запитувати інакше?
mpen

3
З того, що я можу прочитати, dblink не обробляє випадок, коли потрібно запит, який охоплює дві бази даних.
Пол Томблін

26

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;

Примітка. Я надаю цю інформацію для подальшого ознайомлення. Рефренс


21

Я натрапив на це, перш ніж прийшов до того ж висновку щодо запитів між баз даних, як і ви. Що я в кінцевому підсумку робив, - це використовувати схеми для поділу простору таблиці таким чином, щоб я міг тримати таблиці згрупованими, але все-таки запитувати їх усіх.


17
Якщо ви виходите з середовища MySQL, те, що MySQL називає бази даних, дійсно є схемами (CREATE SCHEMA == CREATE DATABASE в MySQL), тож якщо ви переносите щось з MySQL за допомогою декількох баз даних, використовуйте схеми
MkV

10

Просто, щоб додати трохи більше інформації.

Немає можливості запитувати базу даних, крім поточної. Оскільки PostgreSQL завантажує специфічні для бази даних системні каталоги, невідомо, як взагалі повинен вестись запит між БД.

contrib / dblink дозволяє запити між базами даних за допомогою викликів функцій. Звичайно, клієнт може також здійснювати одночасне підключення до різних баз даних і об'єднувати результати на стороні клієнта.

Поширені питання про postgreSQL


5
Ця додаткова інформація може вводити в оману і може змусити користувачів використовувати вищезазначене рішення.
johan855

5

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

Раніше я використовував DB-Link і TDS-link з великим успіхом.


2

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

Це можна зробити за допомогою простих тригерів для вставки, які в свою чергу викликають dblink для оновлення іншої копії. Є також повномасштабні варіанти реплікації (наприклад, Slony), але це поза темою.


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

1

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

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.