带有dblink的postgresql触发器不';我什么也不退

带有dblink的postgresql触发器不';我什么也不退,postgresql,triggers,postgis,dblink,Postgresql,Triggers,Postgis,Dblink,我创建了一个触发器,将插入从database1中的表“mytable_db1”复制到database2上的同一个表“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'

我创建了一个触发器,将插入从database1中的表“mytable_db1”复制到database2上的同一个表“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

有人对我做错了什么有意见吗


谢谢

问题在于,在执行插入时没有传递所有列。因此,NEW中的某些列为null,并且由于使用字符串连接,所以整个
INSERT-to…
string为null

在示例中,此查询返回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;
用于插入整数值和此整数值:

  coalesce(quote_literal(new.name), 'NULL'), 
用于插入文本、时间戳和几何图形值。在insert语句中,始终使用
%s

除此之外,我还对函数进行了以下修改:

  • 检查连接是否已存在
  • 不需要函数
    st\u geometry((st\u AsText())
    ,因为您已经以WKB格式插入了几何体
  • 我使用函数
    format()
    而不是串联运算符
    |

    • 有更好的解决方案

      这里是另一个例子

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

      非常感谢Tommaso!它现在可以工作了!!唯一的问题是我必须重新引入st_几何体(st_AsText())函数的几何体。由于两个表之间的几何体类型不同,它给了我一条错误消息。db1表在PostGIS几何体中,db2表在ArcSDE几何体中。这是更好、更简单的解决方案。我们可以在简单的连接中使用它,如问题中的…“| | quote_nullable(new.name|eng)| |”。。。
      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;