PostgreSQL:関数の引数としてテーブルを渡します


11

TYPEPostgreSQLで発見しています。私は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データセットのタイプではなく、列として認識されるようです。

回答:


13

_source追加されたMWEのパラメーターはどこでも参照されません。source関数本体の識別子には先行アンダースコアがなく、独立して定数テーブル名として解釈されます。

さらに重要なことに、それはとにかくこのように機能しません。SQLでは、DMLステートメントの値のパラメーター化のみが可能です。この関連回答の詳細:

解決

動的SQLを使用EXECUTEしてplpgsql関数で機能させることもできます。詳細:

または、関連する質問と回答についてこの検索を試してください

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/939860またはstackoverflow.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
    )
  );

私が知る限り(同じ問題が発生したため、グーゲル化した後)、テーブルを関数に直接渡すことはできません。

ただし、示されているように、テーブルを[]いくつかの基本的なタイプ(テーブル定義と同様)で構成されるカスタムタイプの配列に変換できます。

その後、関数に入ったら、その配列を渡して、ネストを解除してテーブルに戻すことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.