PLPGSQL如何在execute语句中使用数组?

时间:2010-12-27 13:40:13

标签: database arrays plpgsql

我有一个执行查询的plpgsql函数,但是当我将数组放入其中时它不会解析它,至少它给了我这个错误:

[FAIL]    syntax error at or near "{"
LINE 21:  AND c.category_uuid != ANY({"c0857e20-111e-11e0-ac64-0800...
CONTEXT:  PL/pgSQL function "get_membercategories" line 22 at FOR over EXECUTE statement

This is the complete line:
AND c.category_uuid != ANY({"c0857e20-111e-11e0-ac64-0800200c9a66"})

这是我的功能看起来

CREATE OR REPLACE FUNCTION get_membercategories(in_company_uuid uuid, in_parent_uuid uuid, in_start integer, in_limit integer, in_sortby character varying, in_order character varying, in_querystring character varying, IN in_excludestring UUID[], OUT out_status integer, OUT out_status_description character varying, OUT out_value character varying[]) RETURNS record
LANGUAGE plpgsql
AS $$

DECLARE
 temp_record RECORD;
 altered_parent_uuid UUID;
 temp_out_value VARCHAR[];
 temp_iterator INTEGER := 0; 
 temp_parent_uuidstring VARCHAR;
 temp_excludestring VARCHAR := '';
BEGIN

IF in_parent_uuid IS NOT NULL THEN
    temp_parent_uuidstring := 'AND c.parent_uuid = ''' || in_parent_uuid || '''';
ELSE
    temp_parent_uuidstring := 'AND c.parent_uuid IS NULL';
END IF;

IF in_excludestring IS NOT NULL THEN
    temp_excludestring := 'AND c.category_uuid != ANY(' || in_excludestring || ')';
END IF;


FOR temp_record IN EXECUTE '
 SELECT 
  c.name, 
  c.category_uuid,
  mc.password, 
  (
     SELECT COUNT(*)
     FROM
       targetgroupusers tgu
     WHERE
      tgu.targetgroup_uuid = mc.targetgroup_uuid
  )  AS receivers
FROM
    membercategories AS mc
LEFT JOIN
    categories AS c
ON
    mc.category_uuid = c.category_uuid  
WHERE
   c.isdeleted IS NULL
   ' || temp_excludestring || '
AND
   mc.company_uuid = ''' || in_company_uuid   || '''
   ' || in_querystring || '
   ' || temp_parent_uuidstring || '
ORDER BY
   ' || in_sortby || ' ' || in_order || '
OFFSET
   ' || in_start || '
LIMIT
   ' || in_limit

LOOP   
   temp_out_value[temp_iterator] = ARRAY[temp_record.category_uuid::VARCHAR(36), temp_record.name::CHARACTER VARYING, temp_record.receivers::CHARACTER VARYING, CASE WHEN temp_record.password IS NOT NULL THEN '1' ELSE '0' END];
   temp_iterator = temp_iterator+1;
END LOOP;

out_status := 0;
out_status_description := 'Member categories successfully retrieved';
out_value := temp_out_value;
RETURN;

END$$;

此时我很无能为力,非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

您的问题是数组被扩展为无效字符串(正如您在错误消息中看到的那样)。数组的字符串表示形式需要再次用单引号括起来,然后再转换为approriate数组类型:

以下内容应该有效:

IF in_excludestring IS NOT NULL THEN
    temp_excludestring := 'AND c.category_uuid != ANY(''' || in_excludestring::varchar||'''::UUID[])';
END IF;

请注意,in_excludestring被明确地强制转换为varchar以强制数组的字符串表示形式,用单引号括起来以满足“array literal”语法,然后转换回UUID数组。

结果字符串将如下所示:

category_uuid != ANY ( '{c0857e20-111e-11e0-ac64-0800200c9a66,7fffda0c-11c9-11e0-967c-a300aec7eb54}'::UUID[] )