Работа с массивом в PostgreSQL
Есть две таблицы: grades (которая содержит оценки студентов университета) и students (данные о самих студентов). Передо мной стоит задача вывести имена и фамилии студентов-"должников", заваливших экзамены (соответственно оценка 0 - не явился и 2 - не сдал). Для этого я написал следующую функцию:
CREATE OR REPLACE FUNCTION public.show_badstudents()
RETURNS TABLE(first_name character varying, second_name character varying)
LANGUAGE plpgsql
AS $function$DECLARE
bad int[];
BEGIN
SELECT grade_student into bad from grades
WHERE
grade = 2
or grade = 0;
RETURN QUERY SELECT student_firstName,student_secondName FROM students
where student_id = ANY(bad);
END; $function$
Суть такова: в функции создается массив (bad) и в него заносятся id студентов, у которых в базе оценок нашлись "0" или "2". При вызове функции появляется ошибка: malformed array literal "5". Насколько я понял, веду работу с массивом неправильно.
Помогите, пожалуйста, разобраться! Извините, если вопрос тривиальный, совсем новичок в PostgreSQL :)
Ответы (1 шт):
bad int[];
BEGIN
SELECT grade_student into bad from grades
WHERE
grade = 2
or grade = 0;
Если вы подумали, что select column into array_variable сделает массив вместо вас - это не так.
Синтаксис select into в plpgsql оперирует только первой строкой результата. Но предупреждения об этом языком выведено не будет. Будет ошибка только если указать STRICT
Таким образом здесь вы значение колонки grade_student первой попавшейся строки пытаетесь присвоить массиву, что, конечно, некорректно. Неочевидное сообщение об ошибке от того, что вызывается функция парсера литерала массива - значение массива может быть записано в строковом формате.
Чтобы получить то что вы хотели - вам необходимо сформировать массив в самом запросе:
SELECT array_agg(grade_student) into bad from grades
WHERE
grade = 2
or grade = 0;
И таким образом присвоить переменной уже сформированный массив.
Впрочем, в этой функции массив не нужен вовсе. Задача проще решается одним запросом сразу, а потому более простого language sql достаточно даже для хранимки.