PLPGSQL, как использовать массив в операторе execute? - PullRequest
0 голосов
/ 27 декабря 2010

У меня есть функция 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 Ответ

1 голос
/ 27 декабря 2010

Ваша проблема в том, что массив расширяется до недопустимой строки (как вы можете видеть в сообщении об ошибке).Строковое представление массива должно быть снова заключено в одинарные кавычки, а затем приведено к типу массива approriate:

Должно работать следующее:

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

Обратите внимание, что in_excludestring явно приводится кvarchar для принудительного представления строкового представления массива, заключенного в одинарные кавычки, чтобы удовлетворить синтаксис «литерал массива», а затем приведенный обратно к массиву UUID.

Полученная строка будет выглядеть примерно так:

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