PostgreSQL在同一事务中创建视图并导入外部架构

PostgreSQL在同一事务中创建视图并导入外部架构,postgresql,function,view,dblink,postgres-fdw,Postgresql,Function,View,Dblink,Postgres Fdw,我在两个数据库sourcedb和targetdb之间设置了postgres_fdw,这样我就可以从sourcedb中的模式在targetdb中创建外部数据表 以上所有配置均按预期运行 下一步是每次在sourcedb中的视图中发生更改时重新导入外部模式 为了实现这一点,我在sourcedb中创建了两个函数: fn_创建_视图 fn\u重新创建\u外部数据\u表 在第一个函数fn_create_views中,我在循环中动态创建视图。 循环结束后,我将调用第二个函数,该函数将删除所有外部数据表,并通过

我在两个数据库sourcedb和targetdb之间设置了postgres_fdw,这样我就可以从sourcedb中的模式在targetdb中创建外部数据表

以上所有配置均按预期运行

下一步是每次在sourcedb中的视图中发生更改时重新导入外部模式

为了实现这一点,我在sourcedb中创建了两个函数:

fn_创建_视图 fn\u重新创建\u外部数据\u表 在第一个函数fn_create_views中,我在循环中动态创建视图。 循环结束后,我将调用第二个函数,该函数将删除所有外部数据表,并通过targetDB上的dblink连接导入外部模式

CREATE FUNCTION fn_create_views ()
RETURNS BOOLEAN
LANGUAGE plpgsql
as $$

BEGIN

 FOR .. IN
  EXECUTE '..'
 LOOP

  EXECUTE format('CREATE OR REPLACE VIEW .. AS
                  SELECT * FROM ...', params);

 END LOOP;

 PERFORM fn_recreate_foreign_data_tables('source_foreign_server','target_foreign_server');

return true;

END $$;
我在上面遇到的问题是,在“导入外部架构”过程中,虽然所有外部表都被删除,但“创建视图”没有提交到targetdb架构中

在阅读了SO中的几篇文章之后,一些人建议在同一数据库上通过dblink运行“CREATE VIEW”命令。 显然,这非常有效,因为我猜dblink每次都会打开一个单独的事务

我现在的问题是,有没有另一种更简单的方法来执行上述操作而不单独调用上述函数

谢谢大家!

在将视图与外部表一起使用之前,需要先提交创建视图的本地事务

我看到两种选择:

在对本地数据库的dblink调用中创建视图。然后,当dblink_exec完成时,事务将被提交

在调用fn_create_view和fn_recreate_foreign_data_表之间运行提交


这些观点是什么?删除外部表并在同一事务中再次创建它们应该可以很好地工作。@这些视图是对物化视图的简单选择查询。上述函数的目的是在每次我要更改物化视图查询时重新部署所有物化视图依赖项。@LaurenzAlbe外部表的删除和创建在同一事务中完全有效。但是我想要的是在同一个事务中创建视图、删除和创建外部表。视图和外部表之间的连接到底是什么?视图定义是否使用外部表?@laurenzal相反,外部表指向sourcedb中的每个视图。我正在使用下面的命令IMPORT FOREIGN schema导入的模式中创建所有视图。谢谢!我可能会使用第二个选项,创建一个包装函数,并分别调用这两个函数。
CREATE FUNCTION fn_recreate_foreign_data_tables(_source_foreign_server varchar, _targer_foreign_server varchar)
returns void
language plphsql
as $$

DECLARE 

 _sql_exec text;

BEGIN

 _sql_exec := (SELECT format('SELECT public.dblink_exec(%L,
                    ''DO
                    $dblink$
                    DECLARE
                      l_rec record;
                    BEGIN
                      FOR l_rec IN (SELECT foreign_table_schema, foreign_table_name
                                    FROM information_schema.foreign_tables
                                    WHERE foreign_server_name = ''%L'')
                      LOOP
                         EXECUTE format(''''drop foreign table %I.%I'''', l_rec.foreign_table_schema, l_rec.foreign_table_name);
                      END LOOP;

                      IMPORT FOREIGN SCHEMA ..
                      FROM SERVER foreign_server INTO ..;

                    END $dblink$;'')', _source_foreign_server, _target_foreign_server));

 EXECUTE _sql_exec;

end $$;