Вы действительно должны использовать CLR для этого. Вы далеки от правильной хранимой процедуры, и процедуры sp_OAxxx лучше избегать. Вы неправильно обрабатываете код возврата, используете неверный компонент HTTP и не анализируете результаты с помощью анализатора XML SQL Server. Изначально может показаться, что реализация CLR - это больше работы, но поддержание кода, использующего хранимые процедуры sp_OAxxx и взаимодействие COM, всегда будет болезненным.
Очень немногие люди понимают, как работает этот код, как его изменить, а также является ли он безопасным и надежным. Следующий человек, которому принадлежит ваша кодовая база, вероятно, не один из этих людей Нехорошо иметь такой код в своем проекте.
Если вы действительно используете CLR, вам все равно не следует использовать функцию (хотя технически это возможно). Вы не должны выполнять какой-либо внешний доступ в середине запроса.
В любом случае, вот некоторые исправления к существующему подходу:
declare @serviceURL varchar(max)
declare @returnCode int
declare @errorMessage nvarchar(max)
declare @Object int
declare @hr int
declare @key varchar(2000) = 'Aoj...nFS'
declare @FromAddress nvarchar(max) = '7000 N SH 161, Irving TX 75039'
declare @ToAddress nvarchar(max) = '8617 Garland Rd, Dallas, TX 75218'
set @serviceUrl = 'https://dev.virtualearth.net/REST/v1/Routes/Truck?wp.0=' + @ToAddress + '&wp.1=' + @FromAddress + '&vehicleHazardousMaterials=Flammable&output=xml&key=' + @key
exec @hr = sp_OACreate 'MSXML2.ServerXMLHTTP', @Object OUT;
IF @hr <> 0
begin
set @errorMessage = concat('sp_OACreate failed ', convert(varchar(20),cast(@hr as varbinary(4)),1));
throw 60000, @errorMessage, 1;
end;
begin try
Exec @hr = sp_OAMethod @Object, 'open', NULL, 'get',@serviceUrl, 'false'
IF @hr <> 0
begin
set @errorMessage = concat('open failed ', convert(varchar(20),cast(@hr as varbinary(4)),1));
throw 60000, @errorMessage, 1;
end;
Exec @hr = sp_OAMethod @Object, 'send'
IF @hr <> 0
begin
set @errorMessage = concat('send failed ', convert(varchar(20),cast(@hr as varbinary(4)),1));
throw 60000, @errorMessage, 1;
end;
declare @responseCode int;
Exec @hr = sp_OAGetProperty @Object, 'status', @responseCode out
IF @hr <> 0 or @responseCode <> 200
begin
set @errorMessage = concat('send failed hr:', convert(varchar(20),cast(@hr as varbinary(4)),1),' http response code: ', @responseCode);
throw 60000, @errorMessage, 1;
end;
declare @tmp table(doc xml)
insert into @tmp
exec @hr = sp_OAGetProperty @Object, 'ResponseXML.XML'
IF @hr <> 0
begin
set @errorMessage = concat('ResponseXML.XML failed ', convert(varchar(20),cast(@hr as varbinary(4)),1));
throw 60000, @errorMessage, 1;
end;
WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/search/local/ws/rest/v1')
select doc.value('(//TravelDistance)[1]', 'float') TravelDistance,
doc.value('(//DistanceUnit)[1]', 'nvarchar(20)') DistanceUnit,
doc.value('(//TravelDuration)[1]', 'float') TravelDuration,
doc.value('(//DurationUnit)[1]', 'nvarchar(20)') DurationUnit
from @tmp;
end try
begin catch
exec @hr = sp_OADestroy @Object ;
throw;
end catch