2017-02-09 18 views
1

Я пытаюсь вставить данные в составный массив в моей функции. Он должен принимать данные из типа составного массива параметра INPUT и хранить данные в параметре OUPUT того же типа.Composite Array Тип как параметр OUTPUT в PostgreSQL

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

Это неправильно. Вероятно, вы бы сделали append.

Критическая часть должна выглядеть

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

(небытие (результат)) поле; '{}' является специальным литералом для пустого массива. Значение по умолчанию для PC_COST равно NULL, а NULL + any - NULL снова - поэтому PC_COST должен быть инициализирован для пустого массива - '{}' –