PL / pgSQL函数从不同的数据库返回各种SELECT查询的输出

时间:2018-10-04 09:24:43

标签: sql postgresql plpgsql dynamic-sql

我发现这篇非常有趣的文章:Refactor a PL/pgSQL function to return the output of various SELECT queries 来自Erwin Brandstetter的内容,它描述了如何仅使用一个函数即可返回各种表的所有列:

CREATE OR REPLACE FUNCTION data_of(_table_name anyelement, _where_part text)
  RETURNS SETOF anyelement AS
$func$
BEGIN
   RETURN QUERY EXECUTE 
      'SELECT * FROM ' || pg_typeof(_table_name)::text || ' WHERE ' || _where_part;

END
$func$ LANGUAGE plpgsql;

致电:

SELECT * FROM data_of(NULL::tablename,'1=1 LIMIT 1');

这很好。我需要一个非常相似的解决方案,但要通过dblink从不同数据库上的表中获取数据。这意味着调用NULL::tablename将失败,因为在进行调用的数据库上该表不存在。我不知道如何使这项工作。通过dblink在函数内部连接到其他数据库的任何尝试均无法获得NULL :: tablename的结果。似乎polymorph函数需要一个polymorph参数来创建隐式函数的返回类型。

如果有人能帮助我,我将非常感激。

非常感谢

亲切的问候 布莱恩

1 个答案:

答案 0 :(得分:0)

似乎这个要求比我想象的要难解释。这是第二次尝试测试设置:

数据库1

首先,我们创建一个测试表,其中包含有关数据库1的一些数据:

CREATE TABLE db1_test
(
  id integer NOT NULL,
  txt text
)
WITH (
  OIDS=TRUE
);
INSERT INTO db1_test (id, txt) VALUES(1,'one');
INSERT INTO db1_test (id, txt) VALUES(2,'two');
INSERT INTO db1_test (id, txt) VALUES(3,'three');

现在,我们在数据库1上创建多态函数:

-- create a polymorph function with a polymorph parameter "_table_name" on database 1
-- the return type is set implicit by calling the function "data_of" with the parameter "NULL::[tablename]" and a where part
CREATE OR REPLACE FUNCTION data_of(_table_name anyelement, _where_part text)
  RETURNS SETOF anyelement AS
$func$
BEGIN
   RETURN QUERY EXECUTE 
      'SELECT * FROM ' || pg_typeof(_table_name)::text || ' WHERE ' || _where_part;

END
$func$ LANGUAGE plpgsql;

现在,如果一切都按数据库1的方式工作,我们将进行测试调用

SELECT * FROM data_of(NULL::db1_test, 'id=2');

有效。请注意,我没有指定表db1_test的任何列。现在我们切换到数据库2。

数据库2

这里,我需要从数据库1完全调用以前的 data_of ,尽管 WITHOUT 在调用时就知道所选表的列。不幸的是,这是行不通的,唯一起作用的呼叫是这样的:

SELECT
*
FROM dblink('dbname=[database1] port=[port] user=[user] password=[password]'::text, 'SELECT * FROM data_of(NULL::db1_test, \'id=2\')'::text)
t1(id integer, txt text);

结论

此调用有效,但是如您所见,我需要至少一次指定我要选择的表中所有列的外观。我正在寻找任何绕过此方法的方法,并且可以在不知道数据库1表中的所有列的情况下进行调用。

最终目标

我的最终目标是在数据库2中创建一个类似于

的函数
SELECT * from data_of_dblink('table_name','where_part')

,它在database1上调用internaly data_of(),从而可以选择其中where部分为参数的其他数据库上的表。它应该像静态视图一样工作,但是可以将where部分作为参数传递。

我非常愿意提出建议。

非常感谢

布莱恩