2017-05-05 7 views
3

PostgreSQL 함수의 매개 변수/인수로 (무제한의) 행 배열 (즉, 상수 테이블)을 전달할 수있는 방법은 무엇입니까? 여기 PostgreSQL 함수에 여러 행을 전달하는 방법은 무엇입니까?

는 생각 :

CREATE TYPE foo AS (
    x bigint, 
    y smallint, 
    z varchar(64) 
); 

CREATE OR REPLACE FUNCTION bar(bigint, foo[]) RETURNS TABLE(a bigint, x bigint, y smallint, z varchar(64)) AS 
$$ 
    SELECT $1, x, y, z FROM unnest($2); 
$$ 
LANGUAGE SQL; 

아래 함수 호출 작동하지만 짧은 만들 수있는 방법은 무엇입니까?

SELECT * FROM bar(1, ARRAY[(1,2,'body1'),(2,1,'body2')]::foo[]); 

예를 들어, 우리는 ::foo[] 캐스트를 제거 할 수 있지만, 우리가 그것을 생략 할 수 있도록 일을 다시 작성하는 방법은 무엇입니까?

우리는 가변 인수를 사용해야합니까?

답변

1

PostgreSQL에는 아직 테이블 값 변수가 없으므로 아무 것도 나오지 않습니다. 배열을 전달하는 것은 비효율적이지만 합리적인 크기의 입력에 효과적입니다.

큰 입력의 경우 종종 refcursor를 전달하는 것이 효과적입니다. 어색하지만 시간이 많이 걸리는 테이블과 결합 된 더 큰 데이터 세트에는 실용적 일 수 있습니다.

CREATE OR REPLACE FUNCTION bar(i bigint, c refcursor) RETURNS TABLE(a bigint, x bigint, y smallint, z varchar(64)) AS 
$$ 
DECLARE 
    cursrow foo; 
BEGIN 
    LOOP 
     FETCH NEXT FROM c INTO cursrow; 
     a := i; 
     x := cursrow.x; 
     y := cursrow.y; 
     z := cursrow.z; 
     RETURN NEXT; 
     IF NOT FOUND THEN 
      EXIT; 
     END IF; 
    END LOOP; 
    RETURN; 
END; 
$$; 

사용 :

demo=> BEGIN; 
BEGIN 
demo=> DECLARE "curs1" CURSOR FOR VALUES (1,2,'body1'), (2,1,'body2'); 
DECLARE CURSOR 
craig=> SELECT bar(1, 'curs1'); 
     bar  
--------------- 
(1,1,2,body1) 
(1,2,1,body2) 
(1,,,) 
(3 rows) 

demo=> COMMIT; 
COMMIT 

아름다운하지 않습니다. 하지만 그렇다면 plpgsql은 결코 존재하지 않습니다. (x, y, z) := cursrow 또는 ROW(x, y, z) := cursrow과 같은 것을 쓸 수 있다는 점에서 행값의 lvalues를 갖지 않는 것이 유감스러운 일입니다.

RETURN NEXTrecord 또는 TABLE을 반환하는 경우에만 작동합니다. 당신은 문제 중 하나가 변환 할 수없는 smallint 형태의 사용은 것 같다

RETURN QUERY NEXT i, cursrow.* FROM (FETCH ALL FROM c) AS cursrow; 
1

을 쓸 수 있도록

그리고 슬프게도, 당신은 서브 표현식에 SQL (plpgsql되지 않음) FETCH ALL을 사용할 수 없습니다 암시 적으로 int 상수에서. 그리고 다음 사항을 고려

-- drop function if exists bar(bigint, variadic foo[]); 
-- drop type if exists foo; 

CREATE TYPE foo AS (
    x bigint, 
    y int, -- change type to integer 
    z varchar(64) 
); 

CREATE OR REPLACE FUNCTION bar(bigint, variadic foo[]) RETURNS TABLE(
    a bigint, 
    x bigint, 
    y int, -- and here 
    z varchar(64)) AS 
$$ 
    SELECT $1, x, y, z FROM unnest($2); 
$$ 
LANGUAGE SQL; 

-- Voila! It is even simpler then the using of the ARRAY constructor 
SELECT * FROM bar(1, (1,2,'body1'), (2,1,'body2'), (3,4,'taddy bear')); 

dbfiddle

About variadic parameters