2017-09-24 3 views
1

SELECT 쿼리의 결과를 반환하는 함수를 만들어야합니다. 이 SELECT 쿼리는이 함수 내에 생성 된 몇 가지 임시 테이블 중 하나입니다. 그러한 기능을 만들 수있는 방법이 있습니까? 여기 예제 (아주 단순화 현실에 긴 쿼리를 여러 임시 테이블이있다)이다이러한 임시 테이블을 사용하여 선택 쿼리를 반환하는 임시 테이블을 사용하여 함수 만들기

CREATE OR REPLACE FUNCTION myfunction() RETURNS TABLE (column_a TEXT, column_b TEXT) AS $$ 
BEGIN 
CREATE TEMPORARY TABLE raw_data ON COMMIT DROP 
AS 
SELECT d.column_a, d2.column_b FROM dummy_data d JOIN dummy_data_2 d2 using (id); 

RETURN QUERY (select distinct column_a, column_b from raw_data limit 100); 
END; 
$$ 
LANGUAGE 'plpgsql' SECURITY DEFINER 

내가 얻을 오류 :

[Error] Script lines: 1-19 ------------------------- 
ERROR: RETURN cannot have a parameter in function returning set; 
use RETURN NEXT at or near "QUERY"Position: 237 

가 나는, 명백한 실수에 대해 미리 사과 이거 처음이에요.

ERROR: column "foo" specified more than once

의 의미, 적어도 하나가 :

PSQL 버전은 PostgreSQL의 8.2.15 (그린 플럼 데이터베이스 4.3.12.0 빌드 1)

+0

흥미 롭습니다. 당신이 얻고있는 오류는 무엇입니까? –

+0

SQLFiddle에 코드를 입력하고 수표를 전달하고 예상되는 결과를 반환하는 것처럼 보이거나 그렇지 않을 수도있는 구문 론적 트릭을 사용하여 http://sqlfiddle.com/#!15/874fa/1 –

+0

필수적인 Postgres 버전을 제공하는 것을 잊었습니다. 그리고 '달리게 할 수없는 것'은 내가 들어 본 오류 메시지가 아니다. BTW에는 "psql 함수"가 없습니다. 너는 plpgsql 함수이다. 마지막으로, 무엇 때문에이 임시 테이블이 필요하다고 생각합니까? 아니면 함수? –

답변

1

이 포스트 그레스에 올릴 수있는 가장 가능성이 오류가 두 테이블 모두에 포함 된 더 많은 열 이름 (idUSING 절을 사용하여 하나의 인스턴스로 접혀 있음). 이렇게하면 중복 된 출력 열 이름을 허용하는 일반 SQL SELECT에서 예외가 발생하지 않습니다. 그러나 중복 된 이름을 가진 테이블을 생성 할 수는 없습니다.

문제는 하지 포스트 그레스입니다 (나중에 선언 같은) 그린 플럼, 적용됩니다. 그것은 2005 년 PostgreSQL에서 분리되어 별도로 개발되었습니다. 현재의 Postgres 매뉴얼은 더 이상 적용되지 않습니다. Greenplum documentation을보십시오.

그리고 psql은 표준 PostgreSQL 대화식 터미널 프로그램입니다. 분명히 PostgreSQL 8.2.15와 함께 제공되는 것을 사용하고 있지만 RDBMS는 여전히 Postgres가 아닌 Greenplum입니다.

구문 수정 (먼저 태그처럼, 여전히 관련 포스트 그레스에 대한) :

CREATE OR REPLACE FUNCTION myfunction() 
    RETURNS TABLE (column_a text, column_b text) AS 
$func$ 
BEGIN 
    CREATE TEMPORARY TABLE raw_data ON COMMIT DROP AS 
    SELECT d.column_a, d2.column_b -- explicit SELECT list avoids duplicate column names 
    FROM dummy_data d 
    JOIN dummy_data_2 d2 using (id); 

    RETURN QUERY 
    SELECT DISTINCT column_a, column_b 
    FROM raw_data 
    LIMIT 100; 
END 
$func$ LANGUAGE plpgsql SECURITY DEFINER; 

임시 테이블을 필요가 없을 것입니다 예 - 당신이 동일한 트랜잭션에서 함수 호출 후 임시 테이블에 액세스하지 않는 한 (ON COMMIT DROP). 그렇지 않으면 일반 SQL 함수가 모든면에서 더 좋습니다. 포스트 그레스 그린 플럼 구문 : 아니 적어도

CREATE OR REPLACE FUNCTION myfunction(OUT column_a text, OUT column_b text) 
    RETURNS SETOF record AS 
$func$ 
    SELECT DISTINCT d.column_a, d2.column_b 
    FROM dummy_data d 
    JOIN dummy_data_2 d2 using (id) 
    LIMIT 100; 
$func$ LANGUAGE plpgsql SECURITY DEFINER; 

, it should also work for Greenplum.

이 기능이 남아있는 유일한 이유는 SECURITY DEFINER입니다. 아니면 간단한 SQL 문 (준비된 명령문)을 대신 사용할 수 있습니다.

RETURN QUERY 2008 년 8.3 버전의 PL/pgSQL에 추가되었습니다. 이후에 Greenplum 포크가 추가되었습니다. ORDER BY 임의의 결과를 생성하지 않고 LIMIT : 제외

ERROR: RETURN cannot have a parameter in function returning set; 
use RETURN NEXT at or near "QUERY" Position: 237 

: 당신의 오류 MSG를 설명 할 수 있습니다. 당신이 알고 있다고 생각합니다.


어떤 이유로 당신이 실제로 임시 테이블을 필요로하고 그린 플럼 5.0 like A. Scherbaum suggested로 업그레이드 할 수없는 경우, 당신은 여전히 ​​(포스트 그레스 8.2에서와 같이) 그린 플럼의 4.3.x에서 작동 할 수 있습니다. FOR 루프를 RETURN NEXT과 조합하여 사용하십시오.
예 :

2

그린 플럼 데이터베이스 (5.0)의 최신 버전은 PostgreSQL의 8.3에 따라, 그리고 그것은 RETURN 쿼리 구문을 지원합니다. 기능을 테스트 한 결과 :

PostgreSQL 8.4devel (Greenplum Database 5.0.0-beta.10+dev.726.gd4a707c762 build dev) 
관련 문제