Как отформатировать текст на стороне MS SQL сервера используя массив аргументов?

Используется MS SQL 2019.
В одной таблице сохранены локализованные шаблоны сообщений (например, "An error occurred while processing the file %s.").
В другой таблице сохраняются аргументы в JSON виде, т.к. количество аргументов различается от сообщения к сообщению.
Другими словами, получаем формат строки, получаем аргументы и всё это на стороне клиента форматируем с помощью метода String.format.
Передо мной поставили задачу "перенести" форматирование сообщений на сторону MS SQL сервера. С помощью функции FORMATMESSAGE можно форматировать текст, но проблема в том, что количество аргументов различное и каким образом передать массив аргументов непонятно и возможно ли это в принципе?

DECLARE @json NVARCHAR(MAX);
SET @json = '[1,"abc","def"]';

SELECT FORMATMESSAGE (
    'First arg: %s, second arg: %s, last arg: %s',
    JSON_VALUE( @json, '$')
)
-- выводит: First arg: (null), second arg: (null), last arg: (null)

SELECT FORMATMESSAGE (
    'First arg: %s, second arg: %s, last arg: %s',
    JSON_VALUE( @json, '$[0]'),
    JSON_VALUE( @json, '$[1]'),
    JSON_VALUE( @json, '$[2]')
)
-- выводит: First arg: 1, second arg: abc, last arg: def

Каким образом можно отформатировать текст на стороне MS SQL сервера используя массив аргументов?


Ответы (1 шт):

Автор решения: XelaNimed

Благодаря помощи teran и Akina, создал пользовательскую функцию представленную ниже:

IF OBJECT_ID ( N'dbo.FORMATMESSAGE_JSON', N'FN' ) IS NOT NULL
    DROP FUNCTION dbo.FORMATMESSAGE_JSON;
GO

CREATE FUNCTION dbo.FORMATMESSAGE_JSON( @Format nvarchar(MAX), @Json nvarchar(MAX) )
RETURNS nvarchar(MAX)
AS
BEGIN
    RETURN FORMATMESSAGE(
                @Format,
                JSON_VALUE( @Json, '$[0]' ),
                JSON_VALUE( @Json, '$[1]' ),
                JSON_VALUE( @Json, '$[2]' ),
                JSON_VALUE( @Json, '$[3]' ),
                JSON_VALUE( @Json, '$[4]' ),
                JSON_VALUE( @Json, '$[5]' ),
                JSON_VALUE( @Json, '$[6]' ),
                JSON_VALUE( @Json, '$[7]' ),
                JSON_VALUE( @Json, '$[8]' ),
                JSON_VALUE( @Json, '$[9]' ),
                JSON_VALUE( @Json, '$[10]' ),
                JSON_VALUE( @Json, '$[11]' ),
                JSON_VALUE( @Json, '$[12]' ),
                JSON_VALUE( @Json, '$[13]' ),
                JSON_VALUE( @Json, '$[14]' ),
                JSON_VALUE( @Json, '$[15]' ),
                JSON_VALUE( @Json, '$[16]' ),
                JSON_VALUE( @Json, '$[17]' ),
                JSON_VALUE( @Json, '$[18]' ),
                JSON_VALUE( @Json, '$[19]' )
            )
END;

Используется тривиально:

SELECT dbo.FORMATMESSAGE_JSON(
            '1 arg: %s, 2 arg: %s, 3 arg: %s',
            '[1,"abc","def"]'
        );

Функция ожидает строковое представление JSON-массива, т.е. для передачи подструктуры необходимо воспользоваться JSON_QUERY:

SELECT dbo.FORMATMESSAGE_JSON(
            '1 arg: %s, 2 arg: %s, 3 arg: %s',
            JSON_QUERY( '{"args":[1,"abc","def"]}', '$.args' )
        );

Буду рад предложениям и конструктивной критике.


Ссылки по теме

→ Ссылка