DOC.PROTOTYPES.RU

Имя

dblink - выполнить запрос на внешней базе данных

Синтаксис
SQL код (1)
SELECT *
    FROM dblink([ имя соединения | строка подключения ]::text, [ SQL запрос ]::text, [ остановка в случае ошибки ]::boolean)
        AS t([ поля и типы])::record;
Описание

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

Аргументы

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

SQL запрос - обязательный текстовый параметр, собственно, запрос который мы выполняем на внешней базе данных. Как было сказано выше, данная функция предназначена для запросов, которые возвращают строки, Для других же запросов (INSERT, UPDATE, DELETE) существует функция dblink_exec.

остановка в случае ошибки - необязательный логический параметр, Если он указан как TRUE (что является умолчательным значением когда данный параметр опущен), то ошибка возвращаемая в случае неправильного выполнения удаленного запроса применяется и локально, при FALSE же ошибка выводится только лишь в качестве уведомления, а функция возвращает 0 строк.

Возвращаемые данные

Возвращает массив строк, который возвращает запрос. Строки типа record, поэтому строку еще требуется типизировать, например так.

SQL код (2)
SELECT *
    FROM dblink('remoteserver', 'SELECT id, category, title FROM remote_table WHERE category= 1')
    AS t(id INTEGER, category INTEGER, title TEXT);

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

Примечание

Если dblink возвращает большое количестро записей, то лучше сделать запрос через функцию dblink_open, которая позволит нам считывать строки последовательно не забивая память.

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

SQL код (3)
CREATE VIEW myremote_table AS
    SELECT *
        FROM dblink('myremote_connect', 'SELECT id, category, title FROM myremote_table')
        AS t1(id INTEGER, category INTEGER, title TEXT);

SELECT * FROM myremote_table WHERE category = 1;

Браво! Надеюсь никому не нужно объяснять, что каждый раз мы будем выгребать всю внешнюю таблицу, а потом на уровне VIEW фильтровать?

На самом деле решение более чем простое. Достаточно посмотреть на саму функцию dblink (а это оказывается просто функция, только системная), что бы понять, что написать свою функцию dblink гораздо проще. Итак, функция dblink выглядит так:

SQL код (4)
CREATE FUNCTION dblink(TEXT, TEXT, BOOLEAN) RETURNS SETOF RECORD
    LANGUAGE c STRICT
    AS '$libdir/dblink', 'dblink_record';

Точнее функций dblink на самом деле 4, но они различаются только списком входящих параметров, но как видно, эта фугнкция не блещет оригинальностью, и на редкость проста. Нет, конечно само C библиотека, сложная, не спорю, и строк там больше, но в данном случае она нам не нужна, так как нас больше интересует возвращаемый тип, а он RECORD, что нам совершенно не нужно.

Создаем таблицу, полностью идентичную по структуре внешней таблице, только что индексы вешать не надо. Поясню, почему таблица, а не просто тип - на таблицу мы еще можем повесить красивый триггер на INSERT и вставлять записи во внешнюю таблицу, как в свою родную. Потом создаем дополнительную функцию dblink, которая будет возвращать определенный тип строк основаный на таблице:

SQL код (5)
CREATE TABLE myremote_table (
    id          INTEGER,
    category    INTEGER,
    title       TEXT
);

CREATE FUNCTION myremote_table_dblink(TEXT, TEXT, BOOLEAN) RETURNS SETOF myremote_table
    LANGUAGE c STRICT
    AS '$libdir/dblink', 'dblink_record';

CREATE FUNCTION myremote_table_dblink(TEXT, TEXT) RETURNS SETOF myremote_table
    LANGUAGE c STRICT
    AS '$libdir/dblink', 'dblink_record';

CREATE FUNCTION myremote_table_dblink(TEXT, BOOLEAN) RETURNS SETOF myremote_table
    LANGUAGE c STRICT
    AS '$libdir/dblink', 'dblink_record';

CREATE FUNCTION myremote_table_dblink(TEXT) RETURNS SETOF myremote_table
    LANGUAGE c STRICT
    AS '$libdir/dblink', 'dblink_record';

Для удобства, я сразу создаю все 4 функции для удаленной таблицы, с разным количеством передаваемых параметров

Теперь же можно спокойно делать запросы к внешней таблице, без перечисления полей:

SQL код (6)
SELECT * FROM myremote_table_dblink('remoteserver', 'SELECT * FROM remote_table WHERE category= 1');

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

SQL код (7)
SELECT id, title FROM myremote_table_dblink('remoteserver', 'SELECT * FROM remote_table WHERE category= 1');
Оригинал

http://www.postgresql.org/docs/8.4/static/contrib-dblink.html

Сергей Томулевич aka Phoinix (24.09.2009 ред. 29.09.2009 г.)
Copyright © 2011 Сергей Томулевич