从查询返回的每一行调用set-returns plpgsql函数

时间:2017-12-13 04:15:19

标签: arrays postgresql plpgsql set-returning-functions sql-domain

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

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

result1

我想对执行特定查询所产生的所有 id做同样的事情并最终获得如下结果:

reslt2

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;

1 个答案:

答案 0 :(得分:1)

使用LATERAL联接将您的set-returns函数与查询的其余部分组合在一起。像:

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;

请参阅:

另外,函数(RETURNS)的声明返回类型必须与实际返回的内容相匹配。

在这里使用更简单的SQL函数。您可以使用PL / pgSQL执行相同的操作,在这种情况下使用RETURNS QUERY

您可能对Postgres数组定义的详细信息quoted from the manual:

感兴趣
  

但是,当前实现会忽略任何提供的数组大小   限制,即行为与未指定的数组相同   长度。

     

当前实现不强制声明的数量   尺寸要么。特定元素类型的数组都是   被认为属于同一类型,无论大小或数量   尺寸。因此,声明数组的大小或维数   CREATE TABLE只是文档;它不会影响运行时行为。

意思是,您的domain目前是噪音而没有任何影响(除了并发症)。要在表中实际使用21个元素强制执行1维数组,请使用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(),除非它们有更多功能。