2

参考までに、私はカーソルの使用にまったく慣れていません...したがって、カーソルである関数が1つあります。

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;

SO 次に、別の関数でそれを呼び出して処理する必要があります。

...
--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 の型を宣言する方法がわかりません。ここに私が持っているものがあります:

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 関数は型レコードを取得できません

OK最初に試しました:

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...

Postgres docs でいくつかの構文を見たので、タイプ「テーブル名」を持つ入力パラメーターで関数が作成されていることが示されましたが、これは機能しますが、関数ではなくテーブル名でなければなりません:(私はとても近いことを知っています、私はカーソルを使ってレコードを渡すように言われたので、勉強しました。助けてください。

4

2 に答える 2

1

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 = ?EXPLAINを使用して、クエリがobject_id後でフィルタリングするのではなく、パラメータを2つのサブクエリに取り込むことを確認できるはずです。次に、別の関数から次のように記述できます。

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

TBHPLPGSQLでレコードを渡すためにカーソルを使用することは避けます。実際、何らかの理由で結果セット全体を別の関数に渡す必要がない限り、PLPGSQLの終止符でカーソルを使用することは避けます。ステートメントを単純にループするこの方法ははるかに単純ですが、結果セット全体が最初にメモリに具体化されるという警告があります。

このアプローチのもう1つの欠点は、all_product_promosに列を追加する必要がある場合、「alter view」を使用してビューに列を追加できないため、それに依存するすべての関数を再作成する必要があることです。AFAICTこれは、タイプに列を追加することもできないように見えるためCREATE TYPE、名前付きタイプの作成にも影響します。ALTER TYPE

そのため、「CREATE TYPE」を使用してレコード形式を指定し、関数間で受け渡すことができます。どのリレーションも自動的にと呼ばれるタイプを指定し<relation>%ROWTYPEますが、これも使用できます。

于 2010-04-26T21:26:31.000 に答える
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...
于 2010-04-26T20:22:42.960 に答える