为查询返回的每一行调用 set-returning plpgsql 函数

Call set-returning plpgsql function for each row returned from a query

在我的 Postgres 9.6 数据库中,我有以下自定义域和 table 定义:

create domain lowResData as
    float[21];

create table myRawValues (
    id text,
    myData lowResData,
    xAxis lowResData,
    primary key(id)    
);

以下函数能够为单个项目生成我想要的结果。

create function getData(_id 'text') returns float[] as $$
select myData
from myRawValues
where id = _id
$$ language sql;

create function getAxis(_id 'text') returns float[] as $$
select xAxis 
from myRawValues
where id = _id
$$ language sql;

create function myPlotter(myarray float[], myData float[]) 
returns table (frequency float, amplitude float) as 
$$
select * 
from unnest(myarray, myData) as u;
$$ language sql;

select * from myPlotter(getAxis('123'), getData('123'));

我想对通过执行特定查询生成的 所有 id 执行相同的操作,最终得到如下结果:

create or replace function allIdLowResData() returns setof float[] as
$body$
declare r text;
begin 
    for r in (select id from myRawValues where /*SOME CONDITION*/)
    loop
    return next myPlotter(getAxis(r), getData(r));
    end loop;
    return;
end
$body$
language plpgsql;

使用 LATERAL 连接将您的 set-returning 函数与查询的其余部分结合起来。喜欢:

CREATE OR REPLACE FUNCTION allIdLowResData()
  RETURNS TABLE (frequency float, amplitude float, id text) AS
$func$
SELECT p.*, r.id
FROM   myRawValues r
LEFT   JOIN LATERAL myPlotter(r.xAxis, r.myData) p ON true
WHERE  /*SOME CONDITION*/
$func$  LANGUAGE sql;

参见:

此外,声明的 return 函数类型 (RETURNS) 必须与实际 returned.

匹配

在这里使用更简单的 SQL 函数。您可以对 PL/pgSQL 执行相同的操作,在本例中使用 RETURNS QUERY

您可能对这些有关 Postgres 数组定义的详细信息感兴趣,quoted from the manual:

However, the current implementation ignores any supplied array size limits, i.e., the behavior is the same as for arrays of unspecified length.

The current implementation does not enforce the declared number of dimensions either. Arrays of a particular element type are all considered to be of the same type, regardless of size or number of dimensions. So, declaring the array size or number of dimensions in CREATE TABLE is simply documentation; it does not affect run-time behavior.

意思是,您的 domain 目前只是噪音,没有任何影响(除了并发症)。要在您的 table 中实际强制执行具有恰好 21 个元素的一维数组,请使用 CHECK 约束。喜欢:

CREATE DOMAIN lowResData AS float[21]  -- "[21]" is just for documentation
CONSTRAINT dim1_elem21 CHECK (array_ndims(VALUE) = 1 AND array_length(VALUE, 1) = 21);

我也会放弃 getData()getAxis() 功能,除非它们有更多功能。