Firebird построить CSV-строку из 1 поля из нескольких строк в SQL - PullRequest
1 голос
/ 21 октября 2019

В Firebird 2.5 или 3.0 и Delphi 10.2: в конфигурации master-detail, где всегда есть как минимум 1 и не более 4 или 5 строк подробностей на мастер, мне нужно получить одну строку с определенными полямииз главной строки и поля, которое объединяет 1 поле из каждой строки подробностей в одну строку в формате CSV. Мне нужно делать все это в SQL, а не создавать хранимую процедуру или пользовательскую функцию, потому что я должен делать это с базами данных клиентов и не хочу добавлять объекты в базы данных, которыми я не владею;Я также не хочу использовать вычисляемое поле в коде, если в этом нет необходимости, потому что наши сотрудники службы поддержки должны иметь возможность делать это с помощью сценария в браузере БД, а не встраивать его в программу.

Для моделирования я использую системные таблицы RDB $ INDICES и RDB $ INDEX_SEGMENTS. Получить одну или несколько строк на индекс, каждая с одним полем детализации сегментов, просто:

  SELECT
    r.RDB$INDEX_NAME AS "Index",
    f.RDB$FIELD_POSITION AS "Order",
    f.RDB$FIELD_NAME AS "Fields"
  FROM RDB$INDICES r
    LEFT JOIN RDB$INDEX_SEGMENTS f ON r.RDB$INDEX_NAME = f.RDB$INDEX_NAME
  WHERE r.RDB$FOREIGN_KEY IS NULL
  AND UPPER(r.RDB$RELATION_NAME) = UPPER(:TBLNAME)
  ORDER BY r.RDB$RELATION_NAME, f.RDB$FIELD_POSITION

Но мне нужно вернуть одну строку на индекс, где «Поля» содержат одно или несколько имен сегментов - например,при работе с таблицей с полями SECTIONID и KEYID и составным индексом для этих двух полей столбец «Поля» в приведенном выше запросе будет содержать SECTIONID,KEYID. Я не могу понять, как это сделать, если не добавить вычисляемое поле, которое выполняет отдельный запрос и просматривает этот набор результатов, создавая строку, которая кажется излишне сложной и чрезмерно тяжелой.

Есть ли способ сделать это чисто в SQL в Firebird?

1 Ответ

1 голос
/ 21 октября 2019

Функция LIST() действительно подходит, но ее синтаксис может быть немного сложнее:

SELECT
  r.RDB$INDEX_NAME AS "Index",
  CAST((SELECT LIST(TRIM(RDB$FIELD_NAME), ',')
        FROM (SELECT RDB$FIELD_NAME
              FROM RDB$INDEX_SEGMENTS
              WHERE RDB$INDEX_NAME = r.RDB$INDEX_NAME
              ORDER BY RDB$FIELD_POSITION)) AS VARCHAR(48)) AS "Fields",
FROM RDB$INDICES r
WHERE r.RDB$FOREIGN_KEY IS NULL
  AND UPPER(r.RDB$RELATION_NAME) = UPPER(':TBLNAME')
ORDER BY r.RDB$RELATION_NAME;

Оболочка CAST() предназначена только для преобразования вывода Fields из текстового большого двоичного объекта впростой varchar, так что он легко виден в браузере SQL. Вызов функции TRIM() в предложении LIST() необходим для удаления лишних пробелов в выходных данных, в противном случае вы можете получить возврат SECTIONID ,KEYID.

...