SQL Server 2017 - Как получить JSON вывод хранимой процедуры, содержащей временную таблицу - PullRequest
4 голосов
/ 07 мая 2020

У меня есть хранимая процедура в моей базе данных SQL Server 2017, которая используется node.js API. Эта хранимая процедура выполняет некоторые вычисления, а затем возвращает объект json с использованием FOR JSON PATH.

Теперь я хочу написать несколько тестов в T- SQL, чтобы гарантировать правильное функционирование этой хранимой процедуры. Изменение хранимой процедуры невозможно.

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

USE tempdb
GO
CREATE PROCEDURE dbo.example_sp 
AS
BEGIN
    SELECT val1, val2
    INTO #tmp
    FROM ( VALUES (1, 2), (3, 4)) vals (val1, val2)

    SELECT *
    FROM #tmp
    FOR JSON PATH
END

Теперь, отмечая, что функция FOR JSON PATH приведет к одна ячейка (1 строка, 1 столбец) типа nvarchar, я хотел бы сделать что-то вроде этого, чтобы извлечь объект JSON, чтобы проверить его:

CREATE TABLE #result (json_object varchar(max))

INSERT INTO #result 
    EXEC dbo.example_sp

Но это дает error:

Предложение FOR JSON не допускается в инструкции INSERT.

Хорошо, это расстраивает, но я могу использовать для этого работу openrowset, правильно?

INSERT INTO #result 
    SELECT *
    FROM OPENROWSET('sqlncli', 'Server=(local);Trusted_Connection=yes;', 
                    'EXEC tempdb.dbo.example_sp')

Нет, теперь у меня новая ошибка:

Метаданные не могут быть определены из-за оператора 'Select * from #tmp FOR JSON PATH' в процедуре example_sp используется временная таблица.

Еще более неприятно, но, конечно, я могу использовать трюк WITH RESULT SET, чтобы решить эту проблему?

INSERT INTO #result 
    SELECT *
    FROM OPENROWSET('sqlncli', 'Server=(local);Trusted_Connection=yes;',
                    'EXEC tempdb.dbo.example_sp with result sets ((output varchar(max) NULL))')

Теперь я получаю это ошибка:

Невозможно обработать объект «exe c tempdb.dbo.example_sp с наборами результатов ((output varchar (max) NULL)) ". Поставщик OLE DB «SQLNCLI11» для связанного сервера «(null)» указывает, что либо у объекта нет столбцов, либо у текущего пользователя нет разрешений на этот объект.

Хорошо, чтобы разобраться с этим мы должны использовать SET NOCOUNT ON, что позволяет серверу SQL пропускать некоторую проверку. Окончательная версия:

INSERT INTO #result 
    SELECT *
    FROM OPENROWSET('sqlncli','Server=(local);Trusted_Connection=yes;',
                    'SET NOCOUNT ON; exec tempdb.dbo.example_sp with result sets (( output varchar(max) NULL))')

Что в итоге работает. Я чувствую, что это слишком много для такой простой вещи ... неужели есть способ сделать это лучше?

...