Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL:如何从表中返回动态行而不使用;列定义列表";?_Postgresql_Plpgsql_Polymorphic Associations - Fatal编程技术网

PostgreSQL:如何从表中返回动态行而不使用;列定义列表";?

PostgreSQL:如何从表中返回动态行而不使用;列定义列表";?,postgresql,plpgsql,polymorphic-associations,Postgresql,Plpgsql,Polymorphic Associations,如何在不使用“列定义列表”的情况下从表中动态检索行 我试图通过使用多态类型“anyelement”(伪类型)来实现同样的目的,但得到的错误是“查询的结构和函数结果类型不匹配” 例如:我有一个名为“table1”的表,它包含以下详细信息 --桌子 --作用 create or replace function function1(column_name varchar,relation_name anyelement) returns setof anyelement as $fun$ decla

如何在不使用“列定义列表”的情况下从表中动态检索行

我试图通过使用多态类型“anyelement”(伪类型)来实现同样的目的,但得到的错误是“查询的结构和函数结果类型不匹配”

例如:我有一个名为“table1”的表,它包含以下详细信息

--桌子

--作用

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);

这是因为如果使用
relationship\u name
NULL::table1
值调用函数,则必须返回
SETOF table1

多态参数和结果相互关联,并在解析调用多态函数的查询时解析为特定的数据类型。声明为anyelement的每个位置(参数或返回值)都允许有任何特定的实际数据类型,但在任何给定调用中,它们都必须是相同的实际类型

但你想和我一起回去吗

(slno integer, fname varchar, city varchar, country varchar)
它不是
表1
的行(错过
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::table1
调用函数以获得
relationship\u name
,但如果您愿意,也可以使用varchar获得
relationship\u name
(这将更具可读性,如
列名称
参数).

这是因为如果使用
NULL::table1
的值调用函数以获得
relationship\u name
,则必须返回
SETOF table1

多态参数和结果相互关联,并在解析调用多态函数的查询时解析为特定的数据类型。声明为anyelement的每个位置(参数或返回值)都允许有任何特定的实际数据类型,但在任何给定调用中,它们都必须是相同的实际类型

但你想和我一起回去吗

(slno integer, fname varchar, city varchar, country varchar)
它不是
表1
的行(错过
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::table1
relationship\u name
调用函数,但如果您愿意,也可以使用varchar为
relationship\u name
调用函数(这将更具可读性,就像
column\u name
参数一样)。

任何元素
作为返回类型的处理描述如下:

当函数的返回值声明为多态类型时, 必须至少有一个参数位置也是多态的, 而作为参数提供的实际数据类型决定 该调用的实际结果类型

在您的例子中,这个参数是
关系\u name
类型为
anyelement
,通过传递
NULL::table1
,这确实告诉计划员,这个对
函数1
的特定调用应该返回
table1
的集合。到目前为止还不错

现在的问题是,一旦执行,函数就不会返回表1的集合,而是返回其他内容。这不是执行者所期望的,因此出现了错误

尽管问题的标题是如何返回动态行…,但您似乎想要的是动态列或多态结果集

这对SQL来说是一场艰苦的战斗,因为为了构建查询的执行计划,计划员必须知道每个中间结果的每一列及其类型。如果您使用一个必须执行的函数来设计查询,以便找到其输出的结构,这将产生一个鸡和蛋的问题:计划必须先于执行,它不能依赖于它


PostgreSQL将其动态类型推断技术应用于
anyelement
,在这种约束条件下,它已经在推动实现尽可能多的多态性。

anyelement
作为返回类型的处理描述如下:

当函数的返回值声明为多态类型时, 必须至少有一个参数位置也是多态的, 而作为参数提供的实际数据类型决定 该调用的实际结果类型

在您的例子中,这个参数是
关系\u name
类型为
anyelement
,通过传递
NULL::table1
,这确实告诉计划员,这个对
函数1
的特定调用应该返回
table1
的集合。到目前为止还不错

现在的问题是,一旦执行,函数就不会返回表1的集合,而是返回其他内容。这不是执行者所期望的,因此出现了错误

尽管问题的标题是如何返回动态行…,但您似乎想要的是动态列或多态结果集

这对SQL来说是一场艰苦的战斗,因为为了构建查询的执行计划,计划员必须知道每个中间结果的每一列及其类型。如果您使用一个必须执行的函数来设计查询,以便找到其输出的结构,这将产生一个鸡和蛋的问题:计划必须先于执行,它不能依赖于它


PostgreSQL将其动态类型推断技术应用于
anyelement
,在这种约束下,它已经在尽可能多地实现多态性了。

如果您想要动态列,简短的版本是“您不能”。实现这一点的唯一方法是使用列定义列表,或者通过像json字段一样返回一些行的序列化。顺便问一下,您的
if
块和
else
块之间有什么区别?他们有一个