PostgreSQL:将表作为函数中的参数传递


11

TYPE在PostgreSQL中发现。我有TABLE TYPE一些表必须尊重(接口)。例如:

CREATE TYPE dataset AS(
    ChannelId INTEGER
   ,GranulityIdIn INTEGER
   ,GranulityId INTEGER
   ,TimeValue TIMESTAMP
   ,FloatValue FLOAT
   ,Status BIGINT
   ,QualityCodeId INTEGER
   ,DataArray FLOAT[]
   ,DataCount BIGINT
   ,Performance FLOAT
   ,StepCount INTEGER
   ,TableRegClass regclass
   ,Tags TEXT[]
   ,WeightedMean FLOAT
   ,MeanData FLOAT
   ,StdData FLOAT
   ,MinData FLOAT
   ,MaxData FLOAT
   ,MedianData FLOAT
   ,Percentiles FLOAT[]
);

我可以使用以下模板创建表格:

CREATE TABLE test OF dataset;

我在API中看到了很多选项,但是我有些迷茫。我想知道是否可以将此类型分配给功能INPUT/OUTPUT参数。

假设我有一个FUNCTION调用process,它从数据集中接收记录样本TABLE source,对其进行处理,然后返回TABLE sink相同的TYPE

那就是我想知道是否可以创建一个TYPE如下所示的行为:

CREATE FUNCTION process(
    input dataset
) RETURNS dataset
AS ...

可以这样称呼:

SELECT
    *
FROM
    source, process(input := source) AS sink;

我想知道PostgreSQL是否有可能,请问如何做到这一点。你们中有人知道吗?


这是我正在尝试做的MWE:

DROP TABLE IF EXISTS source;
DROP FUNCTION IF EXISTS process(dataset);
DROP TYPE dataset;

CREATE TYPE dataset AS (
    id INTEGER
   ,t  TIMESTAMP
   ,x  FLOAT
);


CREATE TABLE source OF dataset;
ALTER TABLE source ADD PRIMARY KEY(Id);
INSERT INTO source VALUES
    (1, '2016-01-01 00:00:00', 10.0)
   ,(2, '2016-01-01 00:30:00', 11.0)
   ,(3, '2016-01-01 01:00:00', 12.0)
   ,(4, '2016-01-01 01:30:00',  9.0)
   ;

CREATE OR REPLACE FUNCTION process(
    _source dataset
)
RETURNS SETOF dataset
AS
$BODY$
SELECT * FROM source;
$BODY$
LANGUAGE SQL;

SELECT * FROM process(source);

但是它不会成功,就像将源视为SETOF RECORDS数据集的类型而不是列一样。

Answers:


13

_source添加的MWE中的参数未在任何地方引用。source函数体中的标识符没有前导下划线,并且被独立解释为常量表名。

更重要的是,它无论如何都不会这样工作。SQL仅允许在DML语句中参数化。相关答案的详细信息:

您仍然可以EXECUTE在plpgsql函数中使用动态SQL使其工作。细节:

或尝试通过此搜索找到相关的问题和答案

CREATE TYPE dataset AS (id integer, t timestamp, x float);
CREATE TABLE source OF dataset (PRIMARY KEY(Id));  -- add constraints in same command

INSERT INTO source VALUES
    (1, '2016-01-01 00:00:00', 10.0)
   ,(2, '2016-01-01 00:30:00', 11.0);

CREATE OR REPLACE FUNCTION process(_tbl regclass)
  RETURNS SETOF dataset AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT * FROM ' || _tbl;
END
$func$  LANGUAGE plpgsql;

SELECT * FROM process('source');  -- table name as string literal 

您甚至可以针对任何给定的表进行此工作:

CREATE OR REPLACE FUNCTION process2(_tbl anyelement)
  RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT * FROM ' || pg_typeof(_tbl);
END
$func$  LANGUAGE plpgsql;

SELECT * FROM process2(NULL::source);  -- note the call syntax!!

详细说明:


谢谢回答。Il会在几个小时后检查它。在测试之前,请知道您的解决方案是否接受as的行SELECT。我是说SELECT * FROM process((SELECT * FROM source WHERE cond))
jlandercy

@j:不,您传递一个表。无法传递表本身(没有表变量)。有几种解决方法。相关:stackoverflow.com/a/27853965/939860stackoverflow.com/a/31167928/939860。要处理查询结果,我将使用游标或临时表...
Erwin Brandstetter

0

这将完成您想要的操作,无需任何动态SQL

drop table if exists source cascade;
drop function if exists process(dataset) cascade;
drop type if exists dataset cascade;

create type dataset as (
    id integer
   ,t  timestamp
   ,x  float
);

create table source of dataset;
alter table source add primary key(id);
insert into source values
   (1, '2016-01-01 00:00:00', 10.0)
 , (2, '2016-01-01 00:30:00', 11.0)
;

create or replace function process(
    x_source dataset[]
)
returns setof dataset
as
$body$
select * from unnest(x_source);
$body$
language sql;

select *
from
  process(
    array(
      select
        row(id, t, x)::dataset
      from source
    )
  );

据我所知(由于我遇到了同样的问题,在进行了广泛的胶凝之后),您不能将表直接传递给函数。

但是,如图所示,您可以将表转换为[]包含几种基本类型的自定义类型的数组(类似于表定义)。

然后,可以使用该数组,并将其取消嵌套回到表中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.