2017-02-09 45 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); 

我的功能是

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); 

這是錯誤的。可能你會做追加。

關鍵部分應該看起來像

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; 

你的功能可以通過一個查詢所取代 - 也許少可讀,但顯著速度更快 - 嵌套查詢循環可能會很慢(被更快地運行一個簡單的SELECT比更瑣碎SELECT S):

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

你好帕維爾,你真的讓我的代碼看起來很賤,很不自在。 :)感謝您的幫助。我有一個問題。我如何從輸出訪問一列。我的輸出看起來像這樣「{」(31,23423423)「,」(1,300074321)「}」。爲什麼PC_COST:='{}';這是否像初始化某些東西? – user1720827

+0

(unnest(result))。field; '{}'是空數組的特殊字面值。 PC_COST的默認值爲NULL,並且NULL + any再次爲NULL - 所以PC_COST必須初始化爲空數組 - '{}' –