PostgreSQL:如何从表中返回动态行而不使用;列定义列表";?
如何在不使用“列定义列表”的情况下从表中动态检索行 我试图通过使用多态类型“anyelement”(伪类型)来实现同样的目的,但得到的错误是“查询的结构和函数结果类型不匹配” 例如:我有一个名为“table1”的表,它包含以下详细信息 --桌子 --作用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
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
块之间有什么区别?他们有一个