Напишем более универсальную функцию с дополнительным параметром - максимальное число авторов в названии.
Поскольку функция меняет сигнатуру (число и/или типы входных параметров), ее необходимо сначала удалить, а потом создать заново. В данном случае у функции есть зависимый объект - представление catalog_v, в котором она используется. Представление тоже придется пересоздать (в реальной работе все эти действия надо выполнять в одной транзакции, чтобы изменения вступили в силу атомарно).
=> DROP FUNCTION book_name(integer,text) CASCADE;
NOTICE: drop cascades to view catalog_v DROP FUNCTION
=> CREATE OR REPLACE FUNCTION book_name(book_id integer, title text, maxauthors integer DEFAULT 2) RETURNS text AS $$ DECLARE r record; res text; BEGIN res := shorten(title) || '. '; FOR r IN ( SELECT a.last_name, a.first_name, a.middle_name, ash.seq_num FROM authors a JOIN authorship ash ON a.author_id = ash.author_id WHERE ash.book_id = book_name.book_id ORDER BY ash.seq_num ) LOOP EXIT WHEN r.seq_num > maxauthors; res := res || author_name(r.last_name, r.first_name, r.middle_name) || ', '; END LOOP; res := rtrim(res, ', '); IF r.seq_num > maxauthors THEN res := res || ' и др.'; END IF; RETURN res; END; $$ STABLE LANGUAGE plpgsql;
CREATE FUNCTION
=> CREATE OR REPLACE VIEW catalog_v AS SELECT b.book_id, b.title, b.onhand_qty, book_name(b.book_id, b.title) AS display_name, b.authors FROM books b ORDER BY display_name;
CREATE VIEW
=> SELECT book_id, display_name FROM catalog_v;
book_id | display_name ---------+------------------------------------------------------- 4 | Война и мир. Толстой Л. Н. 2 | Муму. Тургенев И. С. 5 | Путешествия в некоторые удаленные страны.... Свифт Д. 1 | Сказка о царе Салтане. Пушкин А. С. 3 | Трудно быть богом. Стругацкий А. Н., Стругацкий Б. Н. 6 | Хрестоматия. Пушкин А. С., Толстой Л. Н. и др. (6 rows)
Вариант на чистом SQL для сравнения:
=> CREATE OR REPLACE FUNCTION book_name(book_id integer, title text, maxauthors integer DEFAULT 2) RETURNS text AS $$ SELECT shorten(book_name.title) || '. ' || string_agg(author_name(a.last_name, a.first_name, a.middle_name), ', ' ORDER BY ash.seq_num) FILTER (WHERE ash.seq_num <= maxauthors) || CASE WHEN max(ash.seq_num) > maxauthors THEN ' и др.' ELSE '' END FROM authors a JOIN authorship ash ON a.author_id = ash.author_id WHERE ash.book_id = book_name.book_id; $$ STABLE LANGUAGE sql;
CREATE FUNCTION
=> SELECT book_id, display_name FROM catalog_v;
book_id | display_name ---------+------------------------------------------------------- 4 | Война и мир. Толстой Л. Н. 2 | Муму. Тургенев И. С. 5 | Путешествия в некоторые удаленные страны.... Свифт Д. 1 | Сказка о царе Салтане. Пушкин А. С. 3 | Трудно быть богом. Стругацкий А. Н., Стругацкий Б. Н. 6 | Хрестоматия. Пушкин А. С., Толстой Л. Н. и др. (6 rows)