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 문의 값만 매개 변수화 할 수 있습니다 . 이 관련 답변의 세부 사항 :

해결책

EXECUTEplpgsql 함수에서 동적 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은 몇 시간 후에 확인합니다. 테스트하기 전에 알아야 할 것은 솔루션이에서 행을 수신하는 것 SELECT입니다. 내 말은 SELECT * FROM process((SELECT * FROM source WHERE cond)).
jlandercy 2018 년

@ j : 아니요, 테이블 이름 을 전달했습니다 . 테이블 자체를 전달할 수있는 방법은 없습니다 (테이블 변수 없음). 그 주위에는 여러 가지 방법이 있습니다. 관련 : stackoverflow.com/a/27853965/939860 또는 stackoverflow.com/a/31167928/939860 . 쿼리의 결과에 작업에 내가 커서 또는 임시 테이블 ... 사용합니다
어윈 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
    )
  );

내가 말할 수있는 한 (확실히 googeling 한 후 같은 문제가 있기 때문에) 테이블을 함수에 직접 전달할 수 없습니다.

그러나 표시된 것처럼 테이블을 []여러 기본 유형 (테이블 정의와 유사)으로 구성된 사용자 정의 유형 의 배열로 변환 할 수 있습니다 .

그런 다음 함수에 들어가면 해당 배열을 전달하고 테이블로 다시 되돌릴 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.