PostgreSQL的:如何返回从动态表行,而不使用“字段定义列表”?(PostgreSQL: Ho

2019-10-19 18:35发布

如何从表中的行动态,而无需使用“字段定义列表”?

我试图做的,通过使用多态类型“为anyelement”(伪类),但得到错误“查询的结构不匹配函数的结果类型”一样。

例如:我有表称为“表1”,它包括以下细节。

- 表

create table table1
( 
  slno integer,
  fname varchar,
  lname varchar,
  city varchar,
  country varchar
)

- 功能

create or replace function function1(column_name varchar,relation_name anyelement)
returns setof anyelement as
$fun$
declare 
       cname varchar; 
       add_column varchar;
       group_column varchar;
       select_query varchar;
begin
       if column_name='fname' then
          cname:=quote_ident(column_name);
          add_column:='"city"'||','||'"country"';
          group_column:='"slno"'||','||cname||','||'"city"'||','||'"country"';

       else 
          cname:=quote_ident(column_name);
          add_column:='"city"'||','||'"country"';
          group_column:='"slno"'||','||cname||','||'"city"'||','||'"country"';

       end if;

       select_query:='select slno,'||cname||','||add_column||' from '||pg_typeof(relation_name) || 'group by '||group_column;

       return query execute select_query;
end;
$fun$
language plpgsql;

---函数调用

select * from function1('fname',NULL::table1);

Answer 1:

的处理anyelement作为返回类型中描述多态类型 :

当一个函数的返回值被声明为多态类型,作为参数来确定用于该呼叫的实际结果类型必须有至少一个参数位置,这也是多晶型,和提供的实际数据类型。

这种说法,你的情况是relation_name类型为anyelement ,并通过传递NULL::table1 ,这确实讲述了计划者的这一特定呼叫function1应该返回SETOF table1 。 到现在为止还挺好。

现在的问题是,一旦执行,该函数不返回SETOF table1 ,但别的东西。 这不是执行人期待,因此错误。

尽管这个问题是如何返回动态行的标题......你似乎想要的东西是动态的列或多态性的结果集。

这是一场艰苦的战斗与SQL,因为为了建立一个查询的执行计划时,规划明确知道它的类型,每个中间结果的每一列。 如果您使用具有以找到其输出的结构要执行的功能设计您的查询,创建一个鸡和蛋的问题:规划必须先执行,也不能依赖于它。

随着应用到其动态类型infering技术anyelement和PostgreSQL已经推信封尽可能给这个约束来实现尽可能多的多态性。



Answer 2:

这是因为,如果你用的值调用函数NULL::table1relation_name ,你必须返回SETOF table1

多态参数和结果都依赖于对方,当查询调用的函数解析解析为一个特定的数据类型。 每个位置(参数或者返回值)声明成anyelement允许有任何具体的实际数据类型,但在任何给定的调用它们必须是同样的类型。

http://www.postgresql.org/docs/9.3/static/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC

但是你想返回

(slno integer, fname varchar, city varchar, country varchar)

这是不行的table1 (射门lname varchar -第三列)。

如果你愿意打电话与该功能。 'fname''lname' ,你的函数可以简单得多:

create or replace function function1(
    column_name varchar,
    relation_name anyelement
)
returns table (
    slno integer,
    name varchar,
    city varchar,
    country varchar
)
language plpgsql as
$fun$
begin
    return query execute format(
        $sql$
            select slno, %1$I AS name, city, country
            from %2$I
            group by slno, %1$I, city, country
        $sql$,
        column_name,
        pg_typeof(relation_name)
    );
end;
$fun$;

这样一来,你叫你的函数与NULL::table1relation_name ,但您可以使用VARCHAR的relation_name也一样,如果你想(这将是更具可读性,喜欢你的column_name参数)。



文章来源: PostgreSQL: How to return dynamic rows from table without using “column definition list”?