【问题标题】:Composite Array Type as OUTPUT parameter in PostgreSQL复合数组类型作为 PostgreSQL 中的 OUTPUT 参数
【发布时间】:2017-02-09 05:19:34
【问题描述】:

我正在尝试在我的函数中将数据插入复合数组类型。它应该接受来自 INPUT 参数的复合数组类型的数据,并将数据存储到相同类型的 OUPUT 参数中。

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 类型,因此我需要将数据插入到数组中。

【问题讨论】:

    标签: postgresql plpgsql postgresql-9.4


    【解决方案1】:

    当你开发一个函数时,不要使用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 比运行更琐碎的 SELECTs 更快):

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

    【讨论】:

    • 你好 Pavel,你真的让我的代码看起来很便宜。 :) 无论如何感谢您的帮助。我有一个问题。如何从输出中访问一列。我的输出看起来像这样 "{"(31,23423423)","(1,300074321)"}"。以及为什么 PC_COST := '{}';是不是像初始化某些东西一样。
    • (unnest(result)).field; '{}' 是空数组的特殊文字。 PC_COST 的默认值为 NULL,NULL + any 再次为 NULL - 所以 PC_COST 必须初始化为空数组 - '{}'
    猜你喜欢
    • 1970-01-01
    • 2022-10-20
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多