- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
概述
我正在使用 PostgreSQL 9.1.14,并且我试图将一个函数的结果传递给另一个函数。一般的想法(细节,用一个最小的例子,如下)是我们可以写:
select * from (select * from foo ...)
create function foos()
returns setof foo
language sql as $$
select * from foo ...
$$;
select * from foos()
create function more_foos( some_foos setof foo )
language sql as $$
select * from some_foos ... -- or unnest(some_foos), or ???
$$:
select * from more_foos(foos())
-- 1. create a table x with three rows
drop table if exists x cascade;
create table if not exists x (id int, name text);
insert into x values (1,'a'), (2,'b'), (3,'c');
-- 2. xs() is a function with type `setof x`
create or replace function xs()
returns setof x
language sql as $$
select * from x
$$;
-- 3. xxs() should return the context of x, too
-- Ideally the argument would be a `setof x`,
-- but that's not allowed (see below).
create or replace function xxs(x[])
returns setof x
language sql as $$
select x.* from x
join unnest($1) y
on x.id = y.id
$$;
xs()
正如我所料。但是当我尝试传递
xs()
的结果时至
xxs()
,我收到“函数 xxs(x) 不存在”的错误消息:
db=> \i test.sql
DROP TABLE
CREATE TABLE
INSERT 0 3
CREATE FUNCTION
CREATE FUNCTION
db=> select * from xs();
1 | a
2 | b
3 | c
db=> select * from xxs(xs());
ERROR: function xxs(x) does not exist
LINE 1: select * from xxs(xs());
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
xs()
是
setof x
,我原以为它的返回类型是
setof x
(或者可能
x[]
),而不是
x
.根据有关类型的投诉,我可以使用以下任一方法,但是在使用任一定义时,我都可以
select xxs(xs());
,我不能
select * from xxs(xs());
.
create or replace function xxs( x )
returns setof x
language sql as $$
select x.* from x
join unnest(array[$1]) y -- unnest(array[...]) seems pretty bad
on x.id = y.id
$$;
create or replace function xxs( x )
returns setof x
language sql as $$
select * from x
where x.id in ($1.id)
$$;
db=> select xxs(xs());
(1,a)
(2,b)
(3,c)
db=> select * from xxs(xs());
ERROR: set-valued function called in context that cannot accept a set
最佳答案
表函数
我以高速、复杂的数据库迁移为生,使用 SQL 作为客户端和服务器语言(不使用其他语言),全部运行在服务器端,代码很少从数据库引擎中出现。 表函数在我的工作中发挥了巨大的作用 .我不使用“游标”,因为它们太慢而无法满足我的性能要求,而且我所做的一切都是面向结果的。表函数在完全消除游标的使用、实现非常高的速度方面对我有很大帮助,并且对减少代码量和提高简单性做出了巨大贡献。
简而言之,您使用的是 查询 引用两个(或更多)表函数以将数据从一个表函数传递到下一个。 调用表函数的选择查询结果集充当将数据从一个表函数传递到下一个表函数的管道。 在我工作的 DB2 平台/版本上,根据对 9.1 Postgres 手册的快速浏览,在那里也是如此,您只能将单行列值作为输入传递给任何表函数调用,正如你所发现的。 但是,由于表函数调用发生在查询结果集处理的中间,因此您可以获得将整个结果集传递给每个表函数调用的相同效果,尽管在数据库引擎管道中,数据仅传递一行一次给每个表函数。
表函数接受一行输入列,并将单个结果集返回到调用该函数的调用查询(即选择)中。 从表函数传回的结果集列成为调用查询结果集的一部分,因此可用作下一个表函数 的输入。 ,稍后在同一查询中引用,通常作为后续连接。第一个表函数的结果列作为输入(一次一行)提供给第二个表函数,后者将其结果集列返回到调用查询的结果集中。第一个和第二个表函数结果集列现在都是调用查询结果集的一部分,现在可用作第三个表函数的输入(一次一行)。 每个表函数调用通过它返回的列扩展调用查询的结果集。 这可以持续下去,直到您开始达到结果集宽度的限制,这可能因一个数据库引擎而异。
考虑这个示例(当我在 DB2 上工作时,它可能与 Postgres 的语法要求或功能不匹配)。这是我使用表函数的众多设计模式之一,也是比较简单的一种,我认为它非常具有说明性,而且我预计它会具有广泛的吸引力 如果 表函数被大量使用(据我所知它们不是,但我认为它们应该得到更多的关注)。
在此示例中,使用的表函数为:VALIDATE_TODAYS_ORDER_BATCH、POST_TODAYS_ORDER_BATCH 和 DATA_WAREHOUSE_TODAYS_ORDER_BATCH。在我使用的 DB2 版本上,您将表函数包装在“TABLE(在此处放置表函数调用和参数)”中,但是根据快速查看 Postgres 手册,您似乎省略了“TABLE()”包装器。
create table TODAYS_ORDER_PROCESSING_EXCEPTIONS as (
select TODAYS_ORDER_BATCH.*
,VALIDATION_RESULT.ROW_VALID
,POST_RESULT.ROW_POSTED
,WAREHOUSE_RESULT.ROW_WAREHOUSED
from TODAYS_ORDER_BATCH
cross join VALIDATE_TODAYS_ORDER_BATCH ( ORDER_NUMBER, [either pass the remainder of the order columns or fetch them in the function] )
as VALIDATION_RESULT ( ROW_VALID ) --example: 1/0 true/false Boolean returned
left join POST_TODAYS_ORDER_BATCH ( ORDER_NUMBER, [either pass the remainder of the order columns or fetch them in the function] )
as POST_RESULT ( ROW_POSTED ) --example: 1/0 true/false Boolean returned
on ROW_VALIDATED = '1'
left join DATA_WAREHOUSE_TODAYS_ORDER_BATCH ( ORDER_NUMBER, [either pass the remainder of the order columns or fetch them in the function] )
as WAREHOUSE_RESULT ( ROW_WAREHOUSED ) --example: 1/0 true/false Boolean returned
on ROW_POSTED = '1'
where coalesce( ROW_VALID, '0' ) = '0' --Capture only exceptions and unprocessed work.
or coalesce( ROW_POSTED, '0' ) = '0' --Or, you can flip the logic to capture only successful rows.
or coalesce( ROW_WAREHOUSED, '0' ) = '0'
) with data
关于sql - 如何将一组行从一个函数传递到另一个函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26937824/
我是一名优秀的程序员,十分优秀!