Firebird 2.1 Хранированная процедура для объединения текста на нескольких рядах
-
28-09-2019 - |
Вопрос
Я пытаюсь написать сохраненную процедуру для объединения нескольких рядов текста, чтобы вернуть ее как одну строку. Например:
CREATE TABLE TEST (
ID INTEGER,
SEQ INTEGER,
TEXT VARCHAR(255));
COMMIT;
INSERT INTO TEST (ID, SEQ, TEXT) VALUES (1, 1, "LINE 1");
INSERT INTO TEST (ID, SEQ, TEXT) VALUES (1, 2, "LINE 2");
INSERT INTO TEST (ID, SEQ, TEXT) VALUES (1, 3, "LINE 3");
COMMIT;
SET TERM !!;
CREATE PROCEDURE concat_names (iID INTEGER)
RETURNS (CONCAT VARCHAR(2000))
AS
DECLARE VARIABLE name VARCHAR(255);
BEGIN
CONCAT = '';
FOR SELECT TEXT FROM TEST where id=:iID INTO :name
DO BEGIN
CONCAT = CONCAT || name;
END
END!!
SET TERM ;!!
commit;
Однако, когда я бегу:
select concat from concat_names(1);
Это всегда возвращает нулевые ряды.
Есть идеи?
Решение
Вы забываете для приостановки. Ваш продукт должен выглядеть так:
SET TERM !!;
CREATE PROCEDURE concat_names (iID INTEGER)
RETURNS (CONCAT VARCHAR(2000))
AS
DECLARE VARIABLE name VARCHAR(255);
BEGIN
CONCAT = '';
FOR SELECT TEXT FROM TEST where id=:iID INTO :name
DO BEGIN
CONCAT = CONCAT || name;
END
SUSPEND;
END!!
SET TERM ;!!
Вы можете достичь того же результата без сохранения ProC. Использовать список агрегатов в списке:
SELECT LIST(text, '') FROM TEST where id=:iID
Второй параметр списка - это разделитель. Если вы называете список вызовов с именем поля, то запятая «,» будет использоваться для разделения значений.
Другие советы
В случае полевого теста Ban Null, и вы не хотите устанавливать нулю весь результат, полезно использовать:
CONCAT = CONCAT || coalesce(name,'');
вместо
CONCAT = CONCAT || name;
Без использования хранимых PROC и используя версию Firebird 2.5, СПИСОК Функция агрегации вернет «Конкретное соединение строки запятой, ненулевое значение в столбце» *. Использование вышеупомянутой тестовой таблицы, SQL
SELECT LIST(TEXT)
FROM TEST
возвращается
Линия 1, линия 2, линия 3
Это может быть некоторая интерес.
* Взяты с опорной страницы Firebird здесь