Google Geocode API在SQL Server中不返回任何响应,但在浏览器中返回有效地址的有效XML响应

问题描述

我有一个地址3926 Linden St,Bethlehem,PA 18020,用于在sql Server 2016中使用Google Geocode API进行地理编码。这是有效地址,我用来打开HTTP请求的URL是

https://maps.googleapis.com/maps/api/geocode/xml?address=3926+Linden+St,+Bethlehem,+PA+18020&key=MY_API_KEY

我的sql Server SP代码

CREATE PROCEDURE [dbo].[spGeocode]
 @Address varchar(80) = NULL OUTPUT,@City varchar(40) = NULL OUTPUT,@State varchar(40) = NULL OUTPUT,@Country varchar(40) = NULL OUTPUT,@PostalCode varchar(20) = NULL OUTPUT,@County varchar(40) = NULL OUTPUT,@GPSLatitude numeric(9,6) = NULL OUTPUT,@GPSLongitude numeric(9,@MapURL varchar(1024) = NULL OUTPUT

 AS
 BEGIN
 SET NOCOUNT ON

 DECLARE @URL varchar(MAX)
 SET @URL = 'https://maps.googleapis.com/maps/api/geocode/xml?address=' +
 CASE WHEN @Address IS NOT NULL THEN @Address ELSE '' END +
 CASE WHEN @City IS NOT NULL THEN ',' + @City ELSE '' END +
 CASE WHEN @State IS NOT NULL THEN ',' + @State ELSE '' END +
 CASE WHEN @PostalCode IS NOT NULL THEN ',' + @PostalCode ELSE '' END +
 CASE WHEN @Country IS NOT NULL THEN ',' + @Country ELSE '' END +
 '&key=MY_API_KEY'
 SET @URL = REPLACE(@URL,' ','+')

 DECLARE @Response varchar(8000)
 DECLARE @XML xml
 DECLARE @Obj int 
 DECLARE @Result int 
 DECLARE @HTTPStatus int 
 DECLARE @ErrorMsg varchar(MAX)

 EXEC @Result = sp_OACreate 'MSXML2.ServerXMLHttp',@Obj OUT 



 BEGIN TRY
 EXEC @Result = sp_OAMethod @Obj,'open',NULL,'GET',@URL,false

 EXEC @Result = sp_OAMethod @Obj,'setRequestHeader','Content-Type','application/x-www-form-urlencoded'

 EXEC @Result = sp_OAMethod @Obj,send,''

 EXEC @Result = sp_OAGetProperty @Obj,'status',@HTTPStatus OUT 

 EXEC @Result = sp_OAGetProperty @Obj,'responseXML.xml',@Response OUT 

 END TRY
 BEGIN CATCH
 SET @ErrorMsg = ERROR_MESSAGE()
 END CATCH

 EXEC @Result = sp_OADestroy @Obj

 IF (@ErrorMsg IS NOT NULL) OR (@HTTPStatus <> 200) 
 BEGIN
 SET @ErrorMsg = 'Error in spGeocode: ' + ISNULL(@ErrorMsg,'HTTP result is: ' + CAST(@HTTPStatus AS varchar(10)))
 RAISERROR(@ErrorMsg,16,1,@HTTPStatus)
 RETURN 
 END

 SET @XML = CAST(@Response AS XML)

 SET @GPSLatitude = @XML.value('(/GeocodeResponse/result/geometry/location/lat) [1]','numeric(9,6)')
 SET @GPSLongitude = @XML.value('(/GeocodeResponse/result/geometry/location/lng) [1]',6)')

 SET @City = ISNULL(
             ISNULL(@XML.value('(/GeocodeResponse/result/address_component[type="locality"]/long_name) [1]','varchar(40)'),@XML.value('(/GeocodeResponse/result/address_component[type="neighborhood"]/long_name) [1]','varchar(40)')
                    ),@XML.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_3"]/long_name) [1]','varchar(40)')
                    )

 SET @State = @XML.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_1"]/short_name) [1]','varchar(40)') 
 SET @PostalCode = @XML.value('(/GeocodeResponse/result/address_component[type="postal_code"]/long_name) [1]','varchar(20)') 
 SET @Country = @XML.value('(/GeocodeResponse/result/address_component[type="country"]/short_name) [1]','varchar(40)') 
 SET @County = @XML.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_2"]/short_name) [1]','varchar(40)') 

 SET @Address = ISNULL((@XML.value('(/GeocodeResponse/result/address_component[type="street_number"]/long_name) [1]','varchar(40)') + 
                        ' ' +
                        @XML.value('(/GeocodeResponse/result/address_component[type="route"]/long_name) [1]','varchar(40)')
                        ),@XML.value('(/GeocodeResponse/result/formatted_address) [1]','varchar(100)')
                        )

 SET @MapURL = 'https://maps.google.com/maps?f=q&hl=en&q=' + CAST(@GPSLatitude AS varchar(20)) + '+' + CAST(@GPSLongitude AS varchar(20))

 
 SELECT 
 @GPSLatitude AS GPSLatitude,@GPSLongitude AS GPSLongitude,@City AS City,@State AS [State],@PostalCode AS PostalCode,@Address AS [Address],@County AS County,@MapURL AS MapURL,@XML AS XMLResults


END

在这个特定地址上,当我运行SP时

EXEC spGeocode '3926 Linden St,Bethlehem,PA 18020'

Geocode API没有通过上述SP提供响应,但是当我在浏览器中输入整个URL时,它显示了有效的XML响应。还有许多其他有效地址也遇到相同的问题。 sql Server SP显示HTTP请求状态为200,但根本没有错误消息,并且响应为NULL,我认为这意味着没有响应。

更新-仅当Google Geocodes API返回多个结果段时,才会出现此问题。在这种情况下,responseXML.xml将变为NULL。

我想知道如何解决此问题。

解决方法

我终于想通了。

仅当特定地址返回result下的多个GeocodeResponses元素时,才会发生这种情况。发生这种情况时,responseXML.xml的大小将被写入@Response到变量

EXEC @Result = sp_OAGetProperty @Obj,'responseXML.xml',@Response OUT

超出了@Response VARCHAR(8000)的预设长度,因此@Response根本不会写入任何内容,这导致@HTTPStatus为200,但没有@ErrorMsg或{ {1}}。

解决方案是将响应的XML数据写入临时表或表变量中,而不是将其保存在VARCHAR中。修改后的代码应该是(如果使用临时表)在提取responseXML.xml之前创建一个临时表,然后将响应写入该临时表。

@Response