2017-02-09 3 views
1

私の関数で複合配列型にデータを挿入しようとしています。それは、複合配列タイプのINPUTパラメータからのデータを受け入れ、同じタイプのOUPUTパラメータにデータを格納する必要があります。PostgreSQLのOUTPUTパラメータとしての複合配列型

CREATE TYPE public.type_x_type AS (x integer); 

CREATE TYPE public.type_y_type AS(x integer,y integer); 

My機能は

CREATE OR REPLACE FUNCTION GET_PRICE_PC_X 
    (
    IP_PRICE_INFO IN TYPE_X_TYPE[], 
    PC_COST OUT TYPE_Y_TYPE[], 
    OP_RESP_CODE OUT VARCHAR, 
    OP_RESP_MSG OUT VARCHAR 
) 
RETURNS RECORD AS $$ 
DECLARE 
    SELECTED_PRICE CURSOR(IP_PFCNTR INT) 
    FOR 
    SELECT ID, PHONE FROM CUSTOMER WHERE ID=IP_PFCNTR; 
    J NUMERIC(10); 
BEGIN 
J := 0; 
    FOR I IN ARRAY_LOWER(IP_PRICE_INFO,1) .. ARRAY_UPPER(IP_PRICE_INFO,1) 
    LOOP 
    FOR K IN SELECTED_PRICE(IP_PRICE_INFO[I].X) 
    LOOP 
    PC_COST := ROW(K.ID,K.PHONE); 
END LOOP; 
    END LOOP; 
    OP_RESP_CODE :='000'; 
    OP_RESP_MSG :='Success'; 
EXCEPTION 
WHEN OTHERS THEN 
    OP_RESP_CODE :='200'; 
    OP_RESP_MSG :=SQLERRM; 
END; 
$$ language 'plpgsql'; 

select * from GET_PRICE_PC_X(ARRAY[ROW(1)] :: TYPE_X_TYPE[]); 

であり、私は以下のエラーを取得しています。

PC_COST | OP_RESPONSE_CODE | OP_RESP_MSG 
--------------------------------------------------------- 
      | 200    | malformed array literal: "(1,30003)" 

私はそのOUT型をどこかで呼び出すことになるので、配列にデータを挿入する必要があります。

答えて

2

関数を開発するときは、WHEN OTHERSを使用しません。デバッグはひどいです。関数の問題は、配列への複合型の割り当てです。

PC_COST := ROW(K.ID,K.PHONE); 

これは間違っています。おそらく、あなたは追加するでしょう。多分読みにくく、しかし、大幅に高速化 - - 遅くなることがネストされたクエリをループ(速く簡単な一SELECTよりも実行され

重要な部分は

J := 0; PC_COST := '{}'; 
FOR I IN ARRAY_LOWER(IP_PRICE_INFO,1) .. ARRAY_UPPER(IP_PRICE_INFO,1) 
LOOP 
    FOR K IN SELECTED_PRICE(IP_PRICE_INFO[I].X) 
    LOOP 
    PC_COST := PC_COST || ROW(K.ID,K.PHONE)::type_y_type; 
    END LOOP; 
END LOOP; 
あなたの関数は1つのクエリで置き換えることができ

見えるようにすべきですより多くの些細なSELECT秒):

CREATE OR REPLACE FUNCTION public.get_price_pc_x(ip_price_info type_x_type[], 
               OUT pc_cost type_y_type[], 
               OUT op_resp_code character varying, 
               OUT op_resp_msg character varying) 
RETURNS record 
LANGUAGE plpgsql STABLE 
AS $function$ 
BEGIN 
    pc_cost := ARRAY(SELECT ROW(id, phone)::type_y_type 
        FROM customer 
        WHERE id IN (SELECT (unnest(ip_price_info)).x)); 
    OP_RESP_CODE :='000'; 
    OP_RESP_MSG :='Success'; 
EXCEPTION 
    WHEN OTHERS THEN 
    OP_RESP_CODE :='200'; 
    OP_RESP_MSG :=SQLERRM; 
END; 
$function$; 

注:サイクル変数のNUMERICタイプを使用しては間違った考えである - このタイプは高価であり、唯一のお金や貴重な計算のために使用すべきです。ここではintタイプが絶対に正しいです。

通常、あなたがより多くの機能減らすことができます - エラー処理が存在してはならない - この関数が失敗する理由がない - (扱うことができない理由)

CREATE OR REPLACE FUNCTION public.get_price_pc_x(ip_price_info type_x_type[]) 
RETURNS type_y_type[] 
LANGUAGE sql STABLE 
AS $function$ 
    SELECT ARRAY(SELECT ROW(id, phone)::type_y_type 
        FROM customer 
        WHERE id IN (SELECT (unnest(ip_price_info)).x)); 
$function$; 
+0

こんにちはパベルは、あなたが実際に私のコードを不必要なもので安く見せてくれました。 :)とにかく助けてくれてありがとう。一つの質問があります。出力から1列にアクセスするにはどうすればよいですか?私の出力は "{"(31,23423423) "、"(1,300074321) "}"のようになります。そしてなぜPC_COST:= '{}';それは何かを初期化するのと同じですか? – user1720827

+0

(アンネスト(結果))。 '{}'は空の配列の特殊なリテラルです。 PC_COSTのデフォルトはNULLで、NULL + anyはNULLです。したがって、PC_COSTは空の配列に初期化する必要があります。 - '{}' –

関連する問題