PostgreSQL 在同一事务中创建视图和导入外部模式
PostgreSQL Create Views and Import Foreign Schema in the same transaction
我在两个数据库(sourcedb、targetdb)之间设置了postgres_fdw,这样我就可以从 sourcedb 中的模式在 targetdb 中创建外部数据表。
以上所有配置均按预期工作。
下一步是每次我在 sourcedb 中更改视图时重新导入外部模式。
为了实现这一点,我在 sourcedb 中创建了两个函数:
- fn_create_views
- fn_recreate_foreign_data_tables
在第一个函数 (fn_create_views) 中,我在循环中动态创建视图。
循环结束后,我调用第二个函数,该函数删除所有外部数据表并通过连接到 targerdb 的 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 $$;
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 $$;
我遇到的问题是,在 'IMPORT FOREIGN SCHEMA' 期间,'CREATE VIEW' 没有提交,尽管所有外部表都被删除,但它没有将任何内容导入 targetdb 模式。
在阅读了 SO 中的几篇文章后,一些人建议在同一数据库上通过 dblink 运行 'CREATE VIEW' 命令。
显然这很完美,因为我猜 dblink 每次都会打开一个单独的事务。
我现在的问题是,有没有另一种更简单的方法可以在不单独调用上述函数的情况下完成上述操作?
谢谢!
您需要执行 COMMIT
在其中创建视图的本地事务,然后才能将它们用于外部表。
我看到两个选项:
在对本地数据库的 dblink
调用中创建视图。然后事务将在 dblink_exec
完成时提交。
运行 fn_create_views
和 fn_recreate_foreign_data_tables
.
调用之间的 COMMIT
我在两个数据库(sourcedb、targetdb)之间设置了postgres_fdw,这样我就可以从 sourcedb 中的模式在 targetdb 中创建外部数据表。
以上所有配置均按预期工作。
下一步是每次我在 sourcedb 中更改视图时重新导入外部模式。
为了实现这一点,我在 sourcedb 中创建了两个函数:
- fn_create_views
- fn_recreate_foreign_data_tables
在第一个函数 (fn_create_views) 中,我在循环中动态创建视图。 循环结束后,我调用第二个函数,该函数删除所有外部数据表并通过连接到 targerdb 的 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 $$;
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 $$;
我遇到的问题是,在 'IMPORT FOREIGN SCHEMA' 期间,'CREATE VIEW' 没有提交,尽管所有外部表都被删除,但它没有将任何内容导入 targetdb 模式。
在阅读了 SO 中的几篇文章后,一些人建议在同一数据库上通过 dblink 运行 'CREATE VIEW' 命令。 显然这很完美,因为我猜 dblink 每次都会打开一个单独的事务。
我现在的问题是,有没有另一种更简单的方法可以在不单独调用上述函数的情况下完成上述操作?
谢谢!
您需要执行 COMMIT
在其中创建视图的本地事务,然后才能将它们用于外部表。
我看到两个选项:
在对本地数据库的
dblink
调用中创建视图。然后事务将在dblink_exec
完成时提交。运行
fn_create_views
和fn_recreate_foreign_data_tables
. 调用之间的
COMMIT