为查询返回的每一行调用 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()
功能,除非它们有更多功能。
在我的 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()
功能,除非它们有更多功能。