【问题标题】:postgresql trigger with dblink doesn't return anything带有 dblink 的 postgresql 触发器不返回任何内容
【发布时间】:2016-05-19 16:54:34
【问题描述】:

我创建了一个触发器,用于将数据库 1 中的表“mytable_db1”中的插入复制到数据库 2 上的同一个表“mytable_db2”中。两个数据库都在同一台服务器上。

CREATE OR REPLACE FUNCTION trigger_osm_test_insert()
RETURNS trigger AS
$BODY$
BEGIN
  PERFORM dblink_connect('db2', 'dbname=xxx port=5432 user=myusr password=xxx');
  PERFORM dblink_exec('db2', 
  'insert into test.mytable_db2 (osm_id, name, name_eng, name_int, type, z_order, population, last_update, country, iso3, shape)
  values ('||new.osm_id||', '''||new.name||''', '''||new.name_eng||''', '''||new.name_int||''', '''||new.type||''', '||new.z_order||',
  '||new.population||', '''||new.last_update||''', '''||new.country||''', '''||new.iso3||''',
  st_geometry((st_AsText('''||new.shape::text||'''))))');
  PERFORM dblink_disconnect('db2');
  RETURN new;
END;
$BODY$
 LANGUAGE plpgsql VOLATILE
 COST 100;
ALTER FUNCTION trigger_osm_test_insert()
 OWNER TO myusr;

CREATE TRIGGER osm_insert_test
 AFTER INSERT
 ON mytable_db1
 FOR EACH ROW
 EXECUTE PROCEDURE trigger_osm_test_insert();

但是,当我进行如下测试插入时:

insert into test.mytable_db1 (name, shape) values ('test', '0101000020E6100000E0979950035F4A40404B2751B0861CC0');

插入的行已插入 mytable_db1,但触发器似乎无法正常工作,因为 mytable_db2 中没有任何内容。插入没有给我任何来自触发器的错误消息。

我正在使用 postgresql 9.2.2。两个数据库都安装了 dblink 1.0 和 postgis 2.0.6。

有人对我做错了什么有建议吗?

谢谢!

【问题讨论】:

    标签: postgresql triggers postgis dblink


    【解决方案1】:

    问题是您在执行 INSERT 时没有传递所有列。因此,NEW 中的某些列为空,并且因为您使用字符串连接,所以您的整个 INSERT INTO... 字符串为空。

    例如,此查询返回 NULL:

    select NULL || 'some text';
    

    您应该检查每一列是否为空,例如:

    CREATE OR REPLACE FUNCTION trigger_osm_test_insert()
    RETURNS trigger AS
    $BODY$
    DECLARE insert_statement TEXT;
    BEGIN
      
      IF NOT ARRAY['db2'] <@ dblink_get_connections() OR dblink_get_connections() IS NULL THEN
        PERFORM dblink_connect('db2', 'dbname=xxx port=5432 user=xxx password=xxx');
      END IF;
    
      insert_statement =  format('insert into mytable_db2 (
          osm_id, name, name_eng, name_int, type, z_order, 
          population, last_update, country, iso3, shape
          )
          values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)',
      coalesce(new.osm_id::text,'NULL'), 
      coalesce(quote_literal(new.name), 'NULL'), 
      coalesce(quote_literal(new.name_eng), 'NULL'), 
      coalesce(new.name_int::text, 'NULL'), 
      coalesce(quote_literal(new.type),'NULL'), 
      coalesce(new.z_order::text,'NULL'),
      coalesce(new.population::text,'NULL'), 
      coalesce(quote_literal(new.last_update::text),'NULL'), 
      coalesce(quote_literal(new.country),'NULL'), 
      coalesce(quote_literal(new.iso3::text), 'NULL'),
      coalesce(quote_literal(new.shape::text),'NULL')
      );
      PERFORM dblink_exec('db2', insert_statement);
      PERFORM dblink_disconnect('db2');
      RETURN new;
    END;
    $BODY$
     LANGUAGE plpgsql VOLATILE;
    

    我不确定列的类型,所以请检查一下。插入可以为 NULL 的值有点棘手......请使用这个:

      coalesce(new.osm_id::text,'NULL'), 
    

    用于插入整数值和这个:

      coalesce(quote_literal(new.name), 'NULL'), 
    

    用于插入文本、时间戳和几何值。在插入语句中始终使用%s

    除此之外,我对函数做了如下修改:

    • 检查连接是否已经存在
    • 不需要函数st_geometry((st_AsText()),因为您已经插入了 WKB 格式的几何图形
    • 我使用函数format() 而不是连接运算符||

    【讨论】:

    • 非常感谢托马索!它现在有效!唯一的问题是我不得不为几何重新引入 st_geometry(st_AsText()) 函数。由于两个表之间的几何类型不同,它给了我一条错误消息。 db1 表在 PostGIS 几何中,而 db2 表在 ArcSDE 几何中。
    【解决方案2】:

    有更好的解决方案

    这里是另一个例子

    -- Function: flux_tresorerie_historique_backup_row()
    
    -- DROP FUNCTION flux_tresorerie_historique_backup_row();
    
    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(OLD.date_rapprochement_flux),
                        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;
    $BODY$
      LANGUAGE plpgsql VOLATILE
      COST 100;
    ALTER FUNCTION flux_tresorerie_historique_backup_row()
      OWNER TO postgres;
    

    如果您的表格是相同的,您可以像这样使用“格式”

    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;
    

    【讨论】:

    • 这是更好更简单的解决方案。我们可以在简单的串联中使用它,就像在问题中...' || quote_nullable (new.name_eng) || ' ...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 2012-08-23
    相关资源
    最近更新 更多