2010-04-26 4 views
2

을 POSTGRES : 나는 커서를 사용하여 완전히 새로운 오전 ... 그래서 나는 커서 함수 한 한 : 나는 그것을 다른 함수에 SO 다음은 참고

CREATE FUNCTION get_all_product_promos(refcursor, cursor_object_id integer) RETURNS refcursor AS ' 
BEGIN 
    OPEN $1 FOR SELECT * 
       FROM promos prom1 
       JOIN promo_objects ON (prom1.promo_id = promo_objects.promotion_id) 
       WHERE prom1.active = true AND now() BETWEEN prom1.start_date AND prom1.end_date 
        AND promo_objects.object_id = cursor_object_id 
       UNION 
       SELECT prom2.promo_id 
       FROM promos prom2 
       JOIN promo_buy_objects ON (prom2.promo_id = 
        promo_buy_objects.promo_id) 
       LEFT JOIN promo_get_objects ON prom2.promo_id = promo_get_objects.promo_id 
       WHERE (prom2.buy_quantity IS NOT NULL OR prom2.buy_quantity > 0) AND 
        prom2.active = true AND now() BETWEEN prom2.start_date AND 
        prom2.end_date AND promo_buy_objects.object_id = cursor_object_id; 
    RETURN $1; 
END; 
' LANGUAGE plpgsql; 

전화 (? 다음 올바른 가정) 루프가 가져올 사용

... 
--Get the promotions from the cursor 
     SELECT get_all_product_promos('promo_cursor', this_object_id) 
     updated := FALSE; 
     IF FOUND THEN 
     --Then loop through your results 
      LOOP 
       FETCH promo_cursor into this_promotion 
       --Preform comparison logic -this is necessary as this logic is used in other contexts from other functions 
       SELECT * INTO best_promo_results FROM get_best_product_promos(this_promotion, this_object_id, get_free_promotion, get_free_promotion_value, current_promotion_value, current_promotion); 
... 

그래서 여기에 아이디어가 커서에서 선택하는 것입니다 this_promotion로 인출 기록을 넣어 : 그것을 처리 할 필요가있다. 그런 다음 this_promotion의 레코드를 다른 함수로 보냅니다. 나는 get_best_product_promos에서 this_promotion의 타입을 선언 할 것을 알 수 없다. ERROR :

CREATE OR REPLACE FUNCTION get_best_product_promos(this_promotion record, this_object_id integer, get_free_promotion integer, get_free_promotion_value numeric(10,2), current_promotion_value numeric(10,2), current_promotion integer) 
    RETURNS... 

그것은 저에게 말한다 : plpgsql 기능은 첫 번째 유형의 기록을

확인을받을 수 없어 나는 시도 :

CREATE OR REPLACE FUNCTION get_best_product_promos(this_promotion get_all_product_promos, this_object_id integer, get_free_promotion integer, get_free_promotion_value numeric(10,2), current_promotion_value numeric(10,2), current_promotion integer) 
    RETURNS... 

나는 포스트 그레스 워드 프로세서에 약간의 구문을 보았 기 때문에 여기에 내가 무엇을 가지고 이 'tablename'형식의 입력 매개 변수가있는 함수를 만들었지 만 함수가 아닌 tablename이어야합니다. (나는 너무 가깝다는 것을 알고 커서를 사용하여 레코드를 전달한다고 들었습니다. 그래서 공부를 시작했습니다. 도와주세요.

(210)

답변

1

하나의 가능성가 될 것이다 대신 get_all_product_promos에있는 쿼리를 all_product_promos 뷰로 정의하십시오. 그런 다음 함수간에 "all_product_promos % rowtype"유형을 자동으로 전달합니다. 이다

, 같은 :

CREATE VIEW all_product_promos AS 
SELECT promo_objects.object_id, prom1.* 
FROM promos prom1 
JOIN promo_objects ON (prom1.promo_id = promo_objects.promotion_id) 
WHERE prom1.active = true AND now() BETWEEN prom1.start_date AND prom1.end_date 
UNION ALL 
SELECT promo_buy_objects.object_id, prom2.* 
FROM promos prom2 
    JOIN promo_buy_objects ON (prom2.promo_id = promo_buy_objects.promo_id) 
    LEFT JOIN promo_get_objects ON prom2.promo_id = promo_get_objects.promo_id 
WHERE (prom2.buy_quantity IS NOT NULL OR prom2.buy_quantity > 0) 
     AND prom2.active = true 
     AND now() BETWEEN prom2.start_date AND prom2.end_date 

당신은 SELECT * FROM all_product_promos WHERE object_id = ?를 조회하는 것은 오히려 나중에 필터링보다 두 하위 쿼리에 object_id 매개 변수를 사용한다고 설명하여 확인 할 수 있어야한다. 그런 다음 다른 함수에서 당신은 쓸 수 있습니다 :

DECLARE 
    this_promotion all_product_promos%ROWTYPE; 
BEGIN 
    FOR this_promotion IN 
     SELECT * FROM all_product_promos WHERE object_id = this_object_id 
    LOOP 
    -- deal with promotion in this_promotion 
    END LOOP; 
END 

TBH 나는 PLPGSQL 주위 기록을 통과 커서를 사용하지 않는 것입니다. 사실, PLPGSQL full stop에서 커서를 사용하는 것을 피할 수 있습니다. 어떤 이유로 든 전체 결과 집합을 다른 함수에 전달해야하는 경우가 아니면 예외입니다. 이 문을 단순히 반복하는이 메서드는 훨씬 간단하며 전체 결과 집합이 먼저 메모리로 구체화됩니다.

이 접근법의 또 다른 단점은 all_product_promos에 열을 추가해야하는 경우 'alter view'가 포함 된보기에 열을 추가 할 수 없으므로이 열을 사용하는 모든 기능을 다시 만들어야한다는 것입니다. . AFAICT 이것은 으로 명명 된 유형 생성에도 영향을줍니다. ALTER TYPE은 유형에 열을 추가 할 수 없기 때문에 나타납니다.

그래서 "CREATE TYPE"을 사용하여 레코드 형식을 지정하여 함수간에 전달할 수 있습니다.모든 관계에는 자동으로 <relation>%ROWTYPE이라는 유형이 지정되며이 유형도 사용할 수 있습니다.

+0

아,보기가 훨씬 더 의미가 있습니다. 상자 안에서 생각하고있는 기능에 너무 얽매였습니다. 네, 문제가 FETCH 문을 지금 w/문제가 오전 및 오류 루프에 대한 나를 던지고있다. 보기 작업에 익숙해졌으며 커서의 아이디어도 마음에 들지 않았습니다. 이것은 내가 집중적으로 일해야만하는 첫 번째 과정이며 그것은 나를 압도적으로 만든다. 팁을 주셔서 감사합니다. 이제는 2 일 동안 일하려고 시도한 것을 다시 고려해야 만하지만 아아는 여전히 작동하지 않습니다. – KacieHouser

+0

WOOHOO 쿼리가 성공적으로 반환되었습니다. 예! 고마워요. 그리고 나보다 뒤에 그것을 골라 내야하는 누구에게나 이것은 훨씬 더 이해할 수 있습니다. 고맙습니다!!! – KacieHouser

0

답 :

특정 커서 기능의 필드 대신 *의 다음

를 선택 :

다음
CREATE TYPE get_all_product_promos as (buy_quantity integer, discount_amount numeric(10,2), get_quantity integer, discount_type integer, promo_id integer); 

내가 말할 수 있습니다

CREATE OR REPLACE FUNCTION get_best_product_promos(this_promotion get_all_product_promos, this_object_id integer, get_free_promotion integer, get_free_promotion_value numeric(10,2), current_promotion_value numeric(10,2), current_promotion integer) 
    RETURNS... 
+0

이 문제가 해결되지 않았습니다. – KacieHouser

+0

잠깐만 기다려주세요. 다른 곳에서는 다른 오류가 발생합니다. – KacieHouser

+0

FYI 이것은 커서를 사용하는 경우 작동합니다. 원래 코드의 FETCH 문은 내가 또는 Google에서 인식하지 못했던 오류를 던지고 구문 오류가 아니었지만 동의하는 경향이 있으므로보기와 함께갔습니다. araqmod의 모든 점이 있습니다. – KacieHouser