In Firebird 2.5 or 3.0, and Delphi 10.2: In a master-detail configuration, where there's always at least 1 and and not more than 4 or 5 detail rows per master, I need to get a single row that has certain fields from the master row and a field that concatenates 1 field from each detail row into a single CSV-format string. I need to do this all in SQL and not have to create a stored proc or user function, because I need to do this against customer databases and don't want to be adding objects to databases I don't own; I also don't want to use a calculated field in code if I don't have to, because our support guys need to be able to do this by a script in a DB browser rather than building it in into the program.
To model this I'm using the RDB$INDICES and RDB$INDEX_SEGMENTS system tables. Getting one or more rows per index, each with one segments detail field, is straightforward:
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
But what I need is return one row per index, with "Fields" holding one or more segment names - e.g. run against a table with SECTIONID
and KEYID
fields and a compound index on those two fields, the "Fields" column in the above query would hold SECTIONID,KEYID
. I can't for the life of me figure out how to do this short of adding a calculated field that runs a separate query and walks that result set building the string, which seems unnecessarily complex and top-heavy.
Is there a way to do this purely in SQL in Firebird?