Синтаксическая ошибка в функции с использованием dblink для репликации новых данных

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

"syntax error at or near "SELECT"
LINE 5:     SELECT public.dblink_connect('hostaddr=127.0.0.1 port=54...

Я использую версию 9.3.6 на Ubuntu.

CREATE OR REPLACE FUNCTION fn_replicate_insertof_students()
      RETURNS text AS
    $BODY$
    BEGIN
    SELECT public.dblink_connect('hostaddr=127.0.0.1 port=5433 dbname=Utiles user=postgres password=Mypass');

INSERT INTO res_partner (company_id,name,lang,comment,street,supplier,city,zip,country_id,email,phone,date,customer,mobile,ref,state_id,opt_out,city_id,l10n_mx_city2,l10n_mx_street3,l10n_mx_street4,notification_email_send,type,street2,active)
                        VALUES  (1,NEW.name,'es_MX',NEW.comment,NEW.street,false,NEW.city,NEW.zip,NEW.country_id,NEW.email,NEW.phone,NEW.date,true,NEW.mobile,NEW.ref,NEW.state_id,false,NEW.city_id,NEW.l10n_mx_city2,NEW.l10n_mx_street3,NEW.l10n_mx_street4,NEW.notification_email_send,NEW.type,NEW.street2,NEW.active));

SELECT public.dblink_disconnect();

END;
$BODY$ LANGUAGE sql VOLATILE SECURITY DEFINER
SET search_path=myschema, pg_temp;


CREATE TRIGGER tr_replicate_insertof_students
  AFTER INSERT 
  ON res_partner
  FOR EACH ROW
  EXECUTE PROCEDURE fn_replicate_insertof_students();

2 ответа

Решение

@ Ник поднял несколько хороших моментов, но есть еще:

Ваш search_path на самом деле сделано правильно. pg_catalog сначала включается автоматически, если вы явно не поместите его туда в другой позиции.

Что еще более важно, вся функция является бессмысленной в ее нынешнем виде. Вы открываете соединение dblink, но не используете его. Похоже, вы хотите добавить dblink_exec(), Но вам нужно объединить строку запроса с формой значений NEW во-первых, так как NEW не видно на другой стороне червоточины. Итак, у вас есть хороший пример динамического SQL. Довольно крутой старт для начинающего!

Подробный пример кода и объяснение функции с dblink в этом недавнем связанном ответе на dba.SE:

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

CREATE OR REPLACE FUNCTION fn_replicate_insertof_students()
  RETURNS trigger AS
$func$
BEGIN
PERFORM public.dblink_connect('hostaddr=127.0.0.1 port=5433 
                dbname=Utiles user=postgres password=Mypass');

PERFORM public.dblink_exec(format(
   $f$INSERT INTO res_partner (company_id, name, lang, comment, ... )
      VALUES  (1, %L, 'es_MX', %L, ... )$f$
    , NEW.name, NEW.comment, ... ));

PERFORM public.dblink_disconnect();

RETURN NULL;  -- only ok for AFTER trigger

END
$func$ LANGUAGE plpgsql VOLATILE SECURITY DEFINER
                        SET search_path=myschema, pg_temp;
ALTER FUNCTION fn_replicate_insertof_students() OWNER TO postgres;  -- guessing

Также не забудьте установить право владельца на SECURITY DEFINER функция

Рассмотрите возможность использования FOREIGN SERVER, USER MAPPING и файл паролей на целевом сервере. Подробности в ссылке выше.

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

Вы пометили функцию как LANGUAGE sql, который предназначен только для функций, содержащих отдельные операторы SQL. Эта функция написана на LANGUAGE plpgsql,

Он все еще будет жаловаться на SELECT, так как plpgsql требует, чтобы вы на самом деле что-то сделали с результатом SELECT, Вам нужно будет заменить SELECT с PERFORM, чтобы сделать явным, что вы отбрасываете результат.

Другие вопросы по тегам