将dblink生成的记录推出调用存储过程

时间:2011-12-23 17:27:53

标签: postgresql plpgsql dblink

作为调用函数的结果,是否可以简单地传递由dblink()生成的结果记录,如:

create function execute_generic_sql_on_remote_databases(_sql text) 
return set of record
language plpgsql
as $$
declare
  r record; -- this is already not a real record
begin
  -- get connections to several DBs
  ... 
  -- send _sql queries to the DBs
  ... 
  -- get results of query execution
  loop through connections
    for r in select MAGIC from dblink_get_results(conn, _sql) loop
      return next r;
    end loop;
  end loop;
  -- close connections
  ... 
end;
$$;

实际上可以像dblink一样调用此函数:

select * from execute_generic_sql_on_remote_databases('SELECT 1') as r(i int);

但它需要一些MAGIC。 :(

可以轻松地使用plProxy执行此操作,但问题是如何使用dblink完成此操作,如果plpgsql完全可以的话。

1 个答案:

答案 0 :(得分:1)

可能,但处理有点尴尬。您需要提供列定义列表作为函数的附加参数,并构建&执行动态SQL。对于函数调用本身,您需要再次提供相同的列定义列表:

CREATE OR REPLACE FUNCTION f_generic_dblink(text, text) 
RETURNS SETOF record AS
$body$
BEGIN
-- $1 .. sql -String to be executed on remote server
-- $2 .. column type definition string like 'a int, b text'

RETURN QUERY EXECUTE '
SELECT *
FROM   dblink(''port=5432 dbname=falter'', $1) AS (' || $2 || ')'
USING $1;

END;
$body$
    LANGUAGE plpgsql;

致电:

SELECT * FROM f_generic_dblink('SELECT 1', 'i int' ) AS k(i int);

SELECT * FROM f_generic_dblink('SELECT 1, ''foo''', 'i int, t text')
                                                AS k(i int, t text);

小心! $ 2易受SQL注入攻击。

您可能对新的SQL/MED features感兴趣。