Postgres sql函数返回连接的结果

时间:2018-03-29 21:55:53

标签: sql postgresql join stored-procedures

在postgres函数(普通SQL而不是plpgsql)中,如何在table1table2之间返回连接的结果?如果函数定义具有returns setof table1returns setof table2,则它不会起作用,因为它会加入这两个表。如果我returns setof record,我会收到错误。

每个表中都有很多列,因此我希望避免在table()中指定每个列,因为这将是一个维护噩梦,使其与架构更改保持同步。 / p>

1 个答案:

答案 0 :(得分:1)

我看到了两种方式:视图和复合类型。

游乐场:

create table foo(foo_id int primary key, x text);
create table bar(bar_id int primary key, bar_foo_id int references foo(foo_id), y text);
insert into foo values(1, 'a'); insert into bar values(1,1,'b');

您可以创建视图并使用它而不是函数:

create or replace view foobar as select * from foo join bar on foo_id = bar_foo_id;
select * from foobar where x = 'a' and y = 'b';

如果要将其包装到函数中,请使用视图名称作为返回类型:

create function foobar_fn(px text, py text) returns setof foobar language sql as $$
select * from foobar where x like px and y like py $$;

缺点:

  • 所有相关表格中的列名称应该是不同的
  • 每次更改表格结构时都应重新创建视图

另一种方法 - 使用复合类型作为返回类型:

create function foobar_fn_1(px text, py text) returns table (tfoo foo, tbar bar) language sql as $$
select foo, bar  from foo join bar on foo_id = bar_foo_id where x like px and y like py $$;

此函数返回两列,其中一列包含foo表数据,另一列包含bar表数据:

postgres=# select * from foobar_fn_1('a','b');
┌───────┬─────────┐
│ tfoo  │  tbar   │
╞═══════╪═════════╡
│ (1,a) │ (1,1,b) │
└───────┴─────────┘

您可以展开所有内容或分别访问每个字段:

postgres=# select (tfoo).*, (tbar).*, (tfoo).x, (tbar).y from foobar_fn_1('a','b');
┌────────┬───┬────────┬────────────┬───┬───┬───┐
│ foo_id │ x │ bar_id │ bar_foo_id │ y │ x │ y │
╞════════╪═══╪════════╪════════════╪═══╪═══╪═══╡
│      1 │ a │      1 │          1 │ b │ a │ b │
└────────┴───┴────────┴────────────┴───┴───┴───┘

注意列周围的括号。