2016-05-03 10 views
1

後、リモート・データベース内の行を挿入するには:表flux_tresorerie_historiqueからデータを削除した後
を、それが表にこの行を挿入し、別のデータベースのアーカイブに配置されてflux_tresorerie_historiqueトリガー私はこのように動作し、トリガー作成した削除

I dblinkを使用してリモートデータベースにデータを挿入すると、クエリの作成が非常に難しく、特にテーブルに20以上のカラムが含まれていて、他の10個のテーブルに対して同様の関数を作成したいという問題があります。

このタスクを確実にするもう1つの迅速な方法はありますか?正常に動作します

ここでは例:

CREATE OR REPLACE FUNCTION flux_tresorerie_historique_backup_row() 
RETURNS trigger AS 
$BODY$ 
DECLARE date_rapprochement_flux TEXT; 
DECLARE code_commission TEXT; 
DECLARE reference_flux TEXT; 
BEGIN 
IF OLD.date_rapprochement_flux is null 
THEN 
date_rapprochement_flux = 'NULL'; 
ELSE 
date_rapprochement_flux = ''''||to_char(OLD.date_rapprochement_flux, 'YYYY-MM-DD')||''''; 
END IF; 

IF OLD.code_commission is null 
THEN 
code_commission = 'NULL'; 
ELSE 
code_commission = ''''||replace(OLD.code_commission,'''','''''')||''''; 
END IF; 

IF OLD.reference_flux is null 
THEN 
reference_flux = 'NULL'; 
ELSE 
reference_flux = ''''||replace(OLD.reference_flux,'''','''''')||''''; 
END IF; 

perform dblink_connect('dbname=gtr_bd_archive user=postgres  password=postgres'); 
perform dblink_exec('insert into flux_tresorerie_historique values('||OLD.id_flux_historique||','''||OLD.date_operation_flux||''','''||OLD.date_valeur_flux||''','||date_rapprochement_flux||','''||replace(OLD.libelle_flux,'''','''''')||''','||OLD.montant_flux||','||OLD.contre_valeur_dzd||','''||replace(OLD.rib_compte_bancaire,'''','''''')||''','||OLD.frais_flux||','''||replace(OLD.sens_flux,'''','''''')||''','''||replace(OLD.statut_flux,'''','''''')||''','''||replace(OLD.code_devise,'''','''''')||''','''||replace(OLD.code_mode_paiement,'''','''''')||''','''||replace(OLD.code_agence,'''','''''')||''','''||replace(OLD.code_compte,'''','''''')||''','''||replace(OLD.code_banque,'''','''''')||''','''||OLD.date_maj_flux||''','''||replace(OLD.statut_frais,'''','''''')||''','||reference_flux||','||code_commission||','||OLD.id_flux||');'); 
perform dblink_disconnect(); 
RETURN NULL; 
END; 

答えて

1

これは、複製の制限されたアプリケーションです。要件は大きく異なるため、さまざまな状況に対処するさまざまな確立されたソリューションがあります。 Consider the overview in the manual.

あなたの手ニット、トリガーベースのソリューションは、比較的少数の欠失のための1つの実行可能な選択肢です。すべての行に対して個別の接続を開いたり閉じたりすると、かなりのオーバーヘッドが発生します。他にも様々なオプションがあります。


は、データベース・リンクでの作業中、私はいくつかの変更を示唆しています。最も重要なのは

  • format()を使用すると、よりエレガントに文字列をエスケープできます。

  • が通過代わり行全体をパスし、すべての単一の列をエスケープ。

  • 単一のトリガ機能ごとにパスワードを設定しないでください。
    FOREIGN SERVERUSER MAPPINGを使用してください。ここでの詳細な手順:

基本的には、ソースサーバ上たらを実行します。

CREATE SERVER myserver FOREIGN DATA WRAPPER dblink_fdw 
OPTIONS (hostaddr '127.0.0.1', dbname 'gtr_bd_archive'); 

CREATE USER MAPPING FOR role_source SERVER myserver 
OPTIONS (user 'postgres', password 'secret'); 

好ましくは、標的にスーパーユーザとしてログインしていませんサーバ。権限の昇格を避けるために、権限が限定された専用ロールを使用してください。

ターゲットサーバーでpassword fileを使用し、パスワードのないアクセスを許可します。この方法では、パスワードをUSER MAPPINGに保存する必要はありません。この関連の答えの最後の章の説明:

その後

CREATE OR REPLACE FUNCTION pg_temp.flux_tresorerie_historique_backup_row() 
    RETURNS trigger AS 
$func$ 
BEGIN 
    PERFORM dblink_connect('myserver'); -- name of foreign server from above 

    PERFORM dblink_exec(format(
    $$ 
    INSERT INTO flux_tresorerie_historique -- provide target column list! 
    SELECT (r).id_flux_historique 
     , (r).date_operation_flux 
     , (r).date_valeur_flux 
     , (r).date_rapprochement_flux::date -- 'YYYY-MM-DD' is default ISO format anyway 
     , (r).libelle_flux 
     , (r).montant_flux 
     , (r).contre_valeur_dzd 
     , (r).rib_compte_bancaire 
     , (r).frais_flux 
     , (r).sens_flux 
     , (r).statut_flux 
     , (r).code_devise 
     , (r).code_mode_paiement 
     , (r).code_agence 
     , (r).code_compte 
     , (r).code_banque 
     , (r).date_maj_flux 
     , (r).statut_frais 
     , (r).reference_flux 
     , (r).code_commission 
     , (r).id_flux 
    FROM (SELECT %L::flux_tresorerie_historique) t(r) 
    $$, OLD::text)); -- cast whole row type 

    PERFORM dblink_disconnect(); 
    RETURN NULL; -- only for AFTER trigger 
END 
$func$ LANGUAGE plpgsql; 

行タイプがドン場合は、」ターゲット表の列のリストを綴る必要がありますtマッチ。


あなたはこの真剣に考えている場合:

挿入テーブルflux_tresorerie_historique

IEでこの行、あなたが行全体とターゲット行を挿入タイプは同じです(タイムスタンプなどから日付を抽出する必要はありません)。穴の列。

CREATE OR REPLACE FUNCTION flux_tresorerie_historique_backup_row() 
    RETURNS trigger AS 
$func$ 
BEGIN 
    PERFORM dblink_connect('myserver'); -- name of foreign server 

    PERFORM dblink_exec(format(
    $$ 
    INSERT INTO flux_tresorerie_historique 
    SELECT (%L::flux_tresorerie_historique).* 
    $$ 
    , OLD::text)); 

    PERFORM dblink_disconnect(); 
    RETURN NULL; -- only for AFTER trigger 
END 
$func$ LANGUAGE plpgsql; 

関連:

+0

作品たくさんデータをマスターから再挿入し、ストリームレプリケーションを使用しましたが、マスターからデータを削除するとスタンバイから自動的に削除されますが、私のプロを解決できる別のソリューションを提案してくださいblem –

+1

これは、ローカルテーブルとリモートテーブルが同一である場合に最適なソリューションです。ありがとう –

2

あなたはこのためquote_nullableを使用することができます!また、concat_wsは非常に便利来る:リテラル引用されたので、単一引用符の間に非刺さ値を配置することがOKであることを

CREATE OR REPLACE FUNCTION flux_tresorerie_historique_backup_row() 
RETURNS trigger AS 
$BODY$ 
BEGIN 
    perform dblink_connect('dbname=gtr_bd_archive user=postgres password=postgres'); 
    perform dblink_exec('insert into flux_tresorerie_historique values('|| 
    concat_ws(', ', quote_nullable(OLD.id_flux_historique), 
        quote_nullable(OLD.date_operation_flux), 
        quote_nullable(OLD.date_valeur_flux), 
        quote_nullable(to_char(OLD.date_rapprochement_flux, 'YYYY-MM-DD')), 
        quote_nullable(OLD.libelle_flux), 
        quote_nullable(OLD.montant_flux), 
        quote_nullable(OLD.contre_valeur_dzd), 
        quote_nullable(OLD.rib_compte_bancaire), 
        quote_nullable(OLD.frais_flux), 
        quote_nullable(OLD.sens_flux), 
        quote_nullable(OLD.statut_flux), 
        quote_nullable(OLD.code_devise), 
        quote_nullable(OLD.code_mode_paiement), 
        quote_nullable(OLD.code_agence), 
        quote_nullable(OLD.code_compte), 
        quote_nullable(OLD.code_banque), 
        quote_nullable(OLD.date_maj_flux), 
        quote_nullable(OLD.statut_frais), 
        quote_nullable(OLD.reference_flux), 
        quote_nullable(OLD.code_commission), 
        quote_nullable(OLD.id_flux) 
      )||');'); 
    perform dblink_disconnect(); 
    RETURN NULL; 
END; 

注引用符なし1などのPostgreSQL同じように良いリテラル値のためであるので、 quote_nullableによって処理されたすべての列を配置すると便利です。 quote_nullableは既にYYYY-MM-DD形式の日付を出力します(select quote_nullable(now()::date)'2016-05-04'となります)。to_charを削除すると、さらにOLD.date_rapprochement_fluxが簡略化されます。

+1

おかげで、これは私はあなたの答えが、私は削除することによって、スタンバイサーバーにマスターサーバーからデータをアーカイブされて行う必要があると認める罰金 –

関連する問題