Firebird хранимая процедура для объединения всех значений полей из нескольких строк

StackOverflow https://stackoverflow.com/questions/183675

Вопрос

Моя цель - написать сохраненный процесс, который может собирать все значения полей из нескольких строк в одну выходную переменную (возможно, varchar (some_length)). Это может показаться странным решением, но я вполне уверен, что это единственное, что я могу использовать в той ситуации, в которой я нахожусь. Я раньше не использовал Firebird, и хранимые процессы выглядят иначе, чем в других известных системах БД. Мой Firebird 1,5 и диалект 3 (не уверен, что это значит). Так что, может быть, кто-то может помочь мне с примером алгоритма.

Это было полезно?

Решение

Следующая процедура делает то, что вы описываете:

SET TERM !!;
CREATE PROCEDURE concat_names
  RETURNS (concat VARCHAR(2000))
AS
DECLARE VARIABLE name VARCHAR(100);
BEGIN
  concat = '';
  FOR SELECT first_name || ' ' || last_name FROM employee INTO :name
  DO BEGIN
    concat = concat || name || ', ';
  END
END!!
SET TERM ;!!
EXECUTE PROCEDURE concat_names;

Но я подвергаю сомнению мудрость этого решения. Откуда вы знаете, что VARCHAR достаточно длинный для всех строк в нужном вам наборе данных?

Гораздо проще и безопаснее выполнить запрос, чтобы возвращать результат в приложение строка за строкой. У каждого языка программирования приложений есть методы для объединения строк, но что более важно, у них есть более гибкие методы для управления ростом данных.

Кстати, "диалект" в Firebird и InterBase относится к режиму совместимости, который был введен для того, чтобы приложения, разработанные для InterBase 5.x, могли работать с более поздними версиями InterBase и Firebird. Это было почти десять лет назад, и AFAIK сегодня нет необходимости использовать что-либо ниже, чем диалект 3.

Другие советы

При конкатенации вы должны проверить нулевые значения, вот пример для двух полей и разделителя между ними:

    CREATE PROCEDURE CONCAT(
    F1 VARCHAR(385),
    F2 VARCHAR(385),
    SEPARATOR VARCHAR(10))
RETURNS (
    RESULT VARCHAR(780))
AS
begin

  if ((:f1 is not null) and (:f1 <> '')) then
    result = :f1;

  if ((:f2 is not null) and (:f2 <> '')) then
    if ((result is not null) and (result <> '')) then
      begin
        if ((:separator is not null) and (separator <> '')) then
          result = result||separator||f2;
        else
          result = result||f2;
      end
    else
      result = f2;

  suspend;
end

Возврат нескольких строк с использованием хранимых процедур Firebird очень прост.

Не используйте:

execute procedure proc_name(value);

Вместо этого используйте:

select * from proc_name(value);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top