Время прочтения: 5 мин.
Возможно ли обратиться к API только с помощью T-SQL? Спойлер — да! Какие настройки при этом нужны на MS SQL сервере и пошаговое описание процесса описаны в статье.
Возможно ли? Да. Лукавить не буду, это не очень распространённая ситуация, и обычно работа с API происходит из других сред, но может возникнуть потребность обратиться к другому приложению по API именно из SQL кода.
Необходимый подготовительный бэкграунд на сервере. Для возможности вызова методов API на SQL сервере глобальные параметры конфигурации ‘show advanced options’ и ‘Ole Automation Procedures’ должны быть равны 1. По умолчанию они выключены – для их установки можно выполнить следующие SQL команды:
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE;
Первая команда задаёт значение параметра конфигурации, вторая вводит это параметр в действие. NB! Возможность изменения глобальных настроек сервера предоставлена предопределённым ролям sysadmin и serveradmin. Второй параметр конфигурации позволяет включить возможность создание экземпляров объектов OLE-автоматизации, за счёт которых в нашем кейсе будет осуществляться запрос к API.
План:
- Создаём экземпляр объекта и сохраняем его токен
- С использованием токена открываем соединение с удалённым источником
- С использованием токена отправляем запрос
- С использованием токена получаем ответ на запрос
- Уничтожаем токен и работаем с полученными данными
Шаг 1. Создание экземпляра объекта
DECLARE @Object as int
Объявляем переменную для хранения токена экземпляра объекта. Далее вызываем хранимую процедуру sp_OACreate
EXEC sp_OACreate 'MSXML2.ServerXMLHTTP', @Object out
Создаём экземпляр объекта, у метода есть out параметр, значение (токен) которого мы сохраняем и который в дальнейшем будем использовать при вызове других методов. Если учесть возможность возникновения исключения, код лучше модифицировать следующим образом:
DECLARE @ReturnCode as int
EXEC @ReturnCode = sp_OACreate 'MSXML2.ServerXMLHTTP', @Object out
IF @ReturnCode <> 0 GOTO EXCEPTION
При успешном выполнении в переменную @ReturnCode будет записан 0, и соответственно число, отличное от 0, при возникновении исключения. В последнем случае можно вызвать sp_OAGetErrorInfo для получения информации об ошибке, но пропишем в одном месте, чтобы с помощью перехода GOTO EXCEPTION логировать исключения из любого места нашего кода
Шаг 2. Открытие соединения
EXEC @ReturnCode = sp_OAMethod @Object, 'open', NULL, 'get', @url, 'false', 'login', 'password'
IF @ReturnCode <> 0 GOTO EXCEPTION
Сигнатура метода sp_OAMethod: первым аргументом передаётся созданный на предыдущем этапе токен, вторым указывается метод – в нашем случае OPEN открывает HTTP соединение, третьим аргументом указываются выходные значения, в нашем кейсе NULL, а дальше указываются параметры метода: тип запроса (GET, POST, PUT, DELETE…), url адрес API метода, указание на то, синхронный или асинхронный запрос будет выполняться (в нашем кейсе FALSE – запрос асинхронный, в противном случае пришлось бы использовать WaitForResponse), далее указывается логин и пароль авторизации на стороне API (в случае открытого API эти параметры можно опустить)
На этом шаге есть возможность установить дополнительные заголовки запроса с помощью той же хранимой процедуры sp_OAMethod, но в качестве второго аргумента указывая метод SetRequestHeader:
EXEC @ReturnCode = sp_OAMethod @Object, 'SetRequestHeader', NULL, 'Content-Type', 'application/json'
Шаг 3. Отправление запроса
Также используем sp_OAMethod, но уже с методом Send
EXEC @ReturnCode = sp_OAMethod @Object, 'Send', NULL
В нашем кейсе мы рассматриваем пример GET запроса, в случае же POST запроса параметр в теле запроса можно передать дополнительным аргументом этого метода
EXEC @ReturnCode = sp_OAMethod @Object, 'Send', NULL, '{"json object key": "json object value"}'
Шаг 4. Получение ответа
Создаём переменную для записи ответа сервера. Единственный момент – не получится задать ей значение MAX, при этом не удастся получить ответ. Максимальное ограничение в 8000 символов
DECLARE @ResponseText as varchar(8000)
EXEC @ReturnCode = sp_OAMethod @Object, 'ResponseText', @ResponseText output
Шаг 5. Уничтожение токена
Вуаля! Требуемые данные из API получены – можно приступать к парсингу JSON ответа и дальнейшей обработке данных. Но не забываем освободить ресурсы OLE-объекта, которые нам больше не понадобятся с помощью процедуры sp_OADestroy:
EXEС sp_OADestroy @Object
Подводные камни. В правах – для вызова методов OLE автоматизации требуется членство в предопределённой роли сервера sysadmin либо разрешение EXECUTE хранимых процедур OLE объектов.
Обработка ошибок. Приведённые выше шаги были написаны с учётом получения кода ответа метода (записывали в переменную в @ReturnCode), и на первом шаге было показано, что можно при получении кода ошибки обрабатывать исключение переходом GOTO EXCEPTION. Проверка кода ответа и переход в случае значения, отличного от 0, подразумевался в каждом методе OLE автоматизации, но для наглядности был опущен. Так вот, при возникновении исключения можно записывать информацию об этом в табличную переменную
EXCEPTION:
BEGIN
DECLARE @Exception TABLE
(
Error binary(4),
Source varchar(8000),
Description varchar(8000),
HelpFile varchar(8000),
HelpID varchar(8000)
)
INSERT INTO @Exception EXEC sp_OAGetErrorInfo @Object
END
В статье мы рассмотрели случай обращения к API непосредственно из T-SQL кода. Конечно, от задачи к задаче можно предложить для каждого случая своё оптимальное решение. Например, можно обращаться к API из CLR встроенной процедуры или функции (написанной как вариант на C# и развёрнутой на SQL сервере). Это может быть интересно в случаях детальной валидации ответа API, например когда может потребоваться использование регулярных выражений или каких-то специфичных функций, реализованных на платформе .NET, но недоступных для T-SQL, или когда обработка ответа предполагает сложные математические вычисления, а CLR в этом плане как правило обладает большей производительностью. А при некоторых условиях оптимальным вариантом может быть написание SISS пакета для подтягивания данных из внешних источников. Здесь была рассмотрена возможность отправки HTTP запроса и получения ответа от API только средствами T-SQL. В общем, принять к сведению, и использовать обдуманно.