概括获取/创建存储过程从一项到多项

时间:2018-12-21 17:05:17

标签: sql postgresql stored-procedures plpgsql

我有一个运行应用程序的express.js服务器,并且可以从该服务器上使用存储过程在PostgreSQL(版本11)中访问或创建“ variant_id”。

SELECT(get_or_create_variant_id(info_about_variant));

有时候,我还需要使用不同的存储过程来获取大量这些变体ID,这些存储过程需要多个变体并返回多个ID。

SELECT(get_or_create_variant_ids([info_about_variant, info_about_another_variant]));

概括获得/创建单个ID一次完成多个ID的最佳方法是什么?我正在存储过程的LOOP中处理它,但是感觉应该可以使用JOIN。

CREATE OR REPLACE FUNCTION get_or_create_variant_id(
  variant_in VARIANT_TYPE
) RETURNS INT AS $$
DECLARE variant_id_out INTEGER;
BEGIN
  -- I'll be changing this to a ON CONFLICT block shortly
  SELECT(get_variant_id(variant_in) INTO variant_id_out);
  IF (variant_id_out IS NOT NULL) THEN
    RETURN variant_id_out;
  ELSE
    INSERT INTO public.variant (
        [some_fields]
    )
      VALUES (
        [some_values]
      )
      RETURNING variant_id INTO variant_id_out;
    RETURN variant_id_out;
  END IF;
END;
$$ LANGUAGE plpgsql;

-- What is the best way to avoid a loop here?
CREATE OR REPLACE FUNCTION get_or_create_variant_ids(
  variants_in VARIANT_TYPE []
) RETURNS INT [] AS $$
DECLARE variant_ids_out INTEGER [];
DECLARE variants_in_length INTEGER;
DECLARE current_variant_id INTEGER;
BEGIN
  SELECT (array_length(variants_in, 1) INTO variants_in_length);
  FOR i IN 1..variants_in_length LOOP
    SELECT(get_or_create_variant_id(variants_in[i]) INTO current_variant_id);
    SELECT(array_append(variant_ids_out, current_variant_id) INTO variant_ids_out);
  END LOOP;
  RETURN variant_ids_out;
END;
$$ LANGUAGE plpgsql;

-- Everything below is included for completeness, but probably less relevant to my question.
CREATE TYPE variant_type AS (
   [lots of info about the variant]
);
CREATE OR REPLACE FUNCTION get_variant_id(
  variant_in VARIANT_TYPE
) RETURNS INT AS $$
DECLARE variant_id_out INTEGER;
BEGIN
  SELECT variant_id into variant_id_out
  FROM public.variant
  WHERE
     [I want them to]
  ;
  RETURN variant_id_out;
END;
$$ LANGUAGE plpgsql;

1 个答案:

答案 0 :(得分:2)

您可以避免使用内置array functions-在这种情况下使用unnest函数和array constructor来进行显式循环。

CREATE OR REPLACE FUNCTION get_or_create_variant_ids_v2(
  variants_in VARIANT_TYPE []
)
RETURNS integer []
LANGUAGE sql AS $$
  SELECT ARRAY(
    SELECT get_or_create_variant_id(u.v)
    FROM unnest(variants_in) AS u(v)
  )
$$ LANGUAGE sql;