Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server 2016要运行的存储过程_Sql Server_Xml_Bing Maps - Fatal编程技术网

Sql server SQL Server 2016要运行的存储过程

Sql server SQL Server 2016要运行的存储过程,sql-server,xml,bing-maps,Sql Server,Xml,Bing Maps,我创建了一个存储过程,它使用一个临时表来获取Bing maps XML的大量结果,并将其转换为varchar,以便我可以使用它检索多个字段。将其转换为varchar的原因是,对于sp_OAMethod来说,XML太大,并且我的变量始终为空 set @serviceUrl = 'https://dev.virtualearth.net/REST/v1/Routes/Truck?wp.0=' + @ToAddress + '&wp.1=' + @FromAddress + '&ve

我创建了一个存储过程,它使用一个临时表来获取Bing maps XML的大量结果,并将其转换为varchar,以便我可以使用它检索多个字段。将其转换为varchar的原因是,对于sp_OAMethod来说,XML太大,并且我的变量始终为空

set @serviceUrl = 'https://dev.virtualearth.net/REST/v1/Routes/Truck?wp.0=' + @ToAddress  + '&wp.1=' + @FromAddress + '&vehicleHazardousMaterials=Flammable&output=xml&key=XXX-000-XXX'

Exec sp_OACreate 'MSXML2.XMLHTTP', @Object OUT;
Exec sp_OAMethod @Object, 'open', NULL, 'get',@serviceUrl, 'false'
Exec sp_OAMethod @Object, 'send'
Exec sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT

exec @returnCode = sp_oamethod @Object, 'read', @ResponseText out, -1

Create table #tmp(dt xml)

insert into #tmp
    exec @hr = sp_OAGetProperty @Object, 'responseXML.XML'

Set @ResponseText = Convert(varchar(max), (SELECT dt from #tmp))
Drop Table #tmp 

select REPLACE(SUBSTRING(@ResponseText,PATINDEX('%<TravelDistance>%',@ResponseText),21),'<TravelDistance>','') Miles

  ,REPLACE(REPLACE(SUBSTRING(@ResponseText,PATINDEX('%<TravelDuration>%',@ResponseText),21),'<TravelDuration>',''),'<','')/60 TravelMinutes
以上不是完整的代码;为了便于阅读,我对它进行了严格的编辑

我相信有更好的方法可以做到这一点,但这是可行的,而且非常令人兴奋

然而,计划是创建一个可以与其他特殊查询一起使用的函数来检索相同的数据。由于临时表或从函数中填充表,无法作为函数


那么,有人有办法做到这一点吗?

您真的应该使用CLR来实现这一点。这里离正确的存储过程还有很长的路要走,最好避免使用sp_OAxxx过程。您没有正确处理返回代码,使用了错误的HTTP组件,并且没有使用SQL Server的XML解析器解析结果。一开始,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

你真的应该使用CLR。这里离正确的存储过程还有很长的路要走,最好避免使用sp_OAxxx过程。您没有正确处理返回代码,使用了错误的HTTP组件,并且没有使用SQL Server的XML解析器解析结果。一开始,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

您具体希望将哪个部分更改为函数?不能在函数中使用EXEC、CREATE、INSERT或任何其他DDL运算符;我知道的唯一方法是将结果作为临时缓存存储在表中,并使用函数查询该表。但是,您需要使用不同的机制安排对缓存表的更新。我创建的进程将使用两个地址,并从Bing检索行程时间和里程。我意识到一个函数只能有一个返回,所以我基本上会创建两个函数,但我希望能够使用SELECT函数。因此,我需要能够在函数中使用的proc中的一部分是将XML更改为varchar,以使我能够使用XML响应。除非有人有其他方法来实现结果。戴夫·伯勒尔:那么我需要让函数将结果存储在一个表中?是的,如果我要在100行中使用这个函数,周期性地更新表是没有帮助的。考虑把这个逻辑放在CLR函数中。这避免了sp_方法可能出现的资源问题,或者至少使它们更易于管理,并允许您实际使用函数。此外,它允许使用比T-SQL更复杂的方法缓存数据。即便如此,检查您是否不能在客户端执行整个数据检索逻辑并将结果存储在表中也是值得的——这使SQL Server能够专注于它最擅长的功能,即查询关系数据。它处理来自web服务的数据的能力很差。您特别希望将哪个部分更改为功能?不能在函数中使用EXEC、CREATE、INSERT或任何其他DDL运算符;我知道的唯一方法是将结果作为临时缓存存储在表中,并使用函数查询该表。但是,您需要使用不同的机制安排对缓存表的更新。我创建的进程将使用两个地址,并从Bing检索行程时间和里程。我意识到一个函数只能有一个返回,所以我基本上会创建两个函数,但我希望能够使用SELECT函数。因此,我需要能够更改过程中的片段,以便在
函数是将XML更改为varchar以使我能够使用XML响应的地方。除非有人有其他方法来实现结果。戴夫·伯勒尔:那么我需要让函数将结果存储在一个表中?是的,如果我要在100行中使用这个函数,周期性地更新表是没有帮助的。考虑把这个逻辑放在CLR函数中。这避免了sp_方法可能出现的资源问题,或者至少使它们更易于管理,并允许您实际使用函数。此外,它允许使用比T-SQL更复杂的方法缓存数据。即便如此,检查您是否不能在客户端执行整个数据检索逻辑并将结果存储在表中也是值得的——这使SQL Server能够专注于它最擅长的功能,即查询关系数据。它处理来自web服务的数据的能力很差。这非常有效,而且速度非常快。谢谢你的帮助。您能否提供一个示例,说明我如何将sql表中的其他字段与doc.value结果合并在一起?我一直在玩游戏,但在实现这一点上一事无成。如果你将它包装到一个存储过程中,你可以使用INSERT…EXEC加载一个临时表或表变量,然后在后续的查询中加入它。这非常有效而且非常快。谢谢你的帮助。您能否提供一个示例,说明我如何将sql表中的其他字段与doc.value结果合并在一起?如果你把它包装到一个存储过程中,你可以使用INSERT…EXEC加载一个临时表或表变量,然后在后续的查询中加入它。