der-marek
Goto Top

SQL Server Prozeduraufruf - Keine Werte mehr nach 256 aufrufen

Hi,

habe einen SQL Server 2012 Express im Einsatz.
Es gibt eine Prozedur "proc_Geocode", die eine Adresse mittels GoogleMaps API abfragt und die Einzelheiten dieser Abfrage in eine Tabelle schreibt.
Davor habe ich eine Prozedur "proc_gehe_liste_durch" geschrieben, die mittels CURSOR eine Liste mit abzugleichenden Adressen durchgeht und jeweils "proc_Geocode" aufruft.

Soweit so gut, funktioniert auch.
Nach ca. 256 Aufrufen werden zwar noch AdressIDs in die Tabelle geschrieben, aber keine Details der Adressabfrage mehr . Die Felder bleiben leer. Er setzt auch nicht einfach ein paar Datensätze aus. Er schreibt dann einfach keine Details mehr.
Wenn ich die Prozedur "proc_gehe_liste_durch" nun mehrfach für jeweils 250 Datensätze aufrufe funktioniert alles.

Testweise habe ich einen Timer eingebaut, der nach jeder Adressanfrage eine Sekunde wartet. Ergebnis bleibt.

Die Prozedur starte ich jeweils als Administrator direkt über das Management Studio auf dem SQL Server.

Irgendwer eine Idee?

Content-ID: 504699

Url: https://administrator.de/contentid/504699

Ausgedruckt am: 25.11.2024 um 20:11 Uhr

TheJoker2305
TheJoker2305 14.10.2019 um 17:38:01 Uhr
Goto Top
Hallo,

wie sieht denn die Abfrage genau aus ?

Greetz
thejoker2305
Crusher79
Crusher79 14.10.2019 um 18:16:54 Uhr
Goto Top
Hi,

habe mal so ähnlich Entfernung zu PLZ mit echter Route berechnet. Aber allerdings mangels Kreditkarte HERE genommen. Das ganze lief unter C# und die Ergebniss ein die SQL geschrieben.

Wie genau sieht dein Code aus? Was kommt denn als Rückgabewert zurück? Schreibt er nicht in die DB oder ist der Wert schon blank?

Ka ob google beschränkuingen hat. Mit API Key hatte ich bei HERE locker 10.000 Queries durchgeschossen.

mfg Crusher
manuel-r
manuel-r 14.10.2019 aktualisiert um 22:44:36 Uhr
Goto Top
Mit API Key hatte ich bei HERE locker 10.000 Queries durchgeschossen.

Ohne API-Key ist - wenn ich nicht irre - bei 1.000 Geocodings pro Tag Schluss.

Edit: Es sind 1336 API-Calls pro Tag

https://developers.google.com/maps/faq#usage-limits
der-marek
der-marek 16.10.2019 um 19:54:43 Uhr
Goto Top
Also der Code sieht so aus. (maps-key ist natürlich entfernt)
Aufgerufen wird er über eine CURSOR Schleife.

ALTER PROCEDURE [proc_Geocode]
	@AdressID int
AS
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;
	Declare @Adresse nvarchar(255)
	Declare @ResponseText as Varchar(8000);
	Declare @serviceUrl as varchar(500)
	Declare @partial_match as varchar(20)
	Declare @Object as Int;
	Declare @GeocodeID int

	SELECT @GeocodeID = ID from TBL_Adressen_Geocodes where Adress_ID = @AdressID

	SELECT @Adresse = Adresse from avw_Adresse_Zusammen where Adress_ID = @AdressID

	Set @Adresse = REPLACE(@Adresse,' ','+')  
	Set @Adresse = REPLACE(@adresse,'.','')  
	Set @Adresse = REPLACE(@adresse,',','')  
	Set @Adresse = REPLACE(@adresse,'/','')  
	Set @Adresse = REPLACE(@adresse,'ß','ss')  
	Set @Adresse = REPLACE(@adresse,'ä','ae')  
	Set @Adresse = REPLACE(@adresse,'ö','oe')  
	Set @Adresse = REPLACE(@adresse,'ü','ue')  


	set @serviceUrl = 'https://maps.googleapis.com/maps/api/geocode/xml?address='+@Adresse  
	+'&language=de&key=$$KEY$$'  
	print @serviceUrl
	Exec sp_OACreate 'MSXML2.XMLHTTP', @Object OUT;  
	Exec sp_OAMethod @Object, 'open', NULL, 'get',  
					@serviceUrl, --Your Web Service Url (invoked)
					 'false'  
	Exec sp_OAMethod @Object, 'send'  
	Exec sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT  
	

	Declare @Response as XML

	--Select @ResponseText as XMLList
	--set @ResponseText = REPLACE(@responsetext,'ß','ss')  
	--set @ResponseText = REPLACE(@responsetext,'ü','ue')  
	--set @ResponseText = REPLACE(@responsetext,'ä','ae')  
	--set @ResponseText = REPLACE(@responsetext,'ö','oe')  
	--set @ResponseText = REPLACE(@responsetext,'ú','u')  

	set @ResponseText = replace(@responsetext,'<?xml version="1.0" encoding="UTF-8"?>','<?xml version="1.0" encoding="ISO8859-1"?>')  
	
	begin try
		SET @Response = CAST(@ResponseText AS XML);
		-- Insert statements for procedure here
		set @partial_match = @Response.value('(/GeocodeResponse/result/partial_match)[1]', 'varchar(255)')  
		if @partial_match = 'true'  
		begin
			set @partial_match = ' / Partial Match'  
		end
		else
		begin
			set @partial_match = ''  
		end

		if @GeocodeID > 0
		begin
			Update TBL_Adressen_Geocodes set lat = @Response.value('(/GeocodeResponse/result/geometry/location/lat)[1]', 'numeric(18,9)'),lng =   
			@Response.value('(/GeocodeResponse/result/geometry/location/lng)[1]', 'numeric(18,9)'), formatted_address =  
			@Response.value('(/GeocodeResponse/result/formatted_address)[1]', 'nvarchar(255)'),street =  
			@Response.value('(/GeocodeResponse/result/address_component[type="route"]/long_name)[1]', 'nvarchar(50)'), street_number =  
			@Response.value('(/GeocodeResponse/result/address_component[type="street_number"]/short_name)[1]', 'nvarchar(50)'), PLZ =  
			@Response.value('(/GeocodeResponse/result/address_component[type="postal_code"]/short_name)[1]', 'nvarchar(50)'),city =  
			@Response.value('(/GeocodeResponse/result/address_component[type="locality"]/long_name)[1]', 'nvarchar(50)'), county =  
			@Response.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_3"]/long_name)[1]', 'nvarchar(50)'),Bundesland =   
			@Response.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_1"]/long_name)[1]', 'nvarchar(50)'),Bundesland_kurz =   
			@Response.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_1"]/short_name)[1]', 'nvarchar(50)'),Land =  
			@Response.value('(/GeocodeResponse/result/address_component[type="country"]/long_name)[1]', 'nvarchar(50)'),Land_kurz =  
			@Response.value('(/GeocodeResponse/result/address_component[type="country"]/short_name)[1]', 'nvarchar(50)'),GooglePlaceID =  
			@Response.value('(/GeocodeResponse/result/place_id)[1]', 'nvarchar(255)'),GoogleGlobalCode =  
			@Response.value('(/GeocodeResponse/result/plus_code/global_code)[1]', 'nvarchar(255)'),GoogleCompoundCode =  
			@Response.value('(/GeocodeResponse/result/plus_code/compound_code)[1]', 'nvarchar(255)'),GoogleStatus =  
			@Response.value('(/GeocodeResponse/status)[1]', 'nvarchar(20)')+@partial_match, AnlegeDatum = CURRENT_TIMESTAMP where Adress_ID = @AdressID  
		end
		else -- Eintrag noch nicht da
		begin
			insert into TBL_Adressen_Geocodes (Adress_ID,lat,lng,formatted_address,street,street_number,PLZ,city,county,Bundesland,Bundesland_kurz,Land,Land_kurz,GooglePlaceID,GoogleGlobalCode,GoogleCompoundCode,GoogleStatus) Values
			(@AdressID,@Response.value('(/GeocodeResponse/result/geometry/location/lat)[1]', 'numeric(18,9)'),  
			@Response.value('(/GeocodeResponse/result/geometry/location/lng)[1]', 'numeric(18,9)'),  
			@Response.value('(/GeocodeResponse/result/formatted_address)[1]', 'nvarchar(255)'),  
			@Response.value('(/GeocodeResponse/result/address_component[type="route"]/long_name)[1]', 'nvarchar(50)'),  
			@Response.value('(/GeocodeResponse/result/address_component[type="street_number"]/short_name)[1]', 'nvarchar(50)'),  
			@Response.value('(/GeocodeResponse/result/address_component[type="postal_code"]/short_name)[1]', 'nvarchar(50)'),  
			@Response.value('(/GeocodeResponse/result/address_component[type="locality"]/long_name)[1]', 'nvarchar(50)'),  
			@Response.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_3"]/long_name)[1]', 'nvarchar(50)'),  
			@Response.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_1"]/long_name)[1]', 'nvarchar(50)'),  
			@Response.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_1"]/short_name)[1]', 'nvarchar(50)'),  
			@Response.value('(/GeocodeResponse/result/address_component[type="country"]/long_name)[1]', 'nvarchar(50)'),  
			@Response.value('(/GeocodeResponse/result/address_component[type="country"]/short_name)[1]', 'nvarchar(50)'),  
			@Response.value('(/GeocodeResponse/result/place_id)[1]', 'nvarchar(255)'),  
			@Response.value('(/GeocodeResponse/result/plus_code/global_code)[1]', 'nvarchar(255)'),  
			@Response.value('(/GeocodeResponse/result/plus_code/compound_code)[1]', 'nvarchar(255)'),  
			@Response.value('(/GeocodeResponse/status)[1]', 'nvarchar(20)')+@partial_match )  
		end
	end try
	Begin catch
		if @GeocodeID > 0
		begin
			Update TBL_Adressen_Geocodes set GoogleStatus = 'SQL Fehler' where Adress_ID = @AdressID  
		end
		else
		begin
			insert into TBL_Adressen_Geocodes (Adress_ID,GoogleStatus) Values (@AdressID,'SQL FEHLER')  
		end
	end catch	
	
END
der-marek
der-marek 16.10.2019 aktualisiert um 20:00:30 Uhr
Goto Top
Eine Begrenzung nach Zeit, hatte ich erst vermutet. Daher der Schleifenaufruf mit der Wartezeit von je 1 Sekunde. Bringt aber nix.

Edit: Lt. Google FAQ gibts in solchen Fällen auch einen Fehlercode zurück. Damit ich ungefähr weiß was da passiert, schreibe ich den Fehlercode immer mit in den "Googlestatus". Bei den "leeren" Datensätzen existiert aber kein Fehlercode.
Entweder kommt keine XML von Google zurück, oder SQL fragt ab einer gewissen Anzahl nicht mehr an. (was ich eher glaube)
der-marek
der-marek 16.10.2019 um 20:15:01 Uhr
Goto Top
Ich habs !

SQL scheint die sp_OAMethod zu limitieren. Hat vllt. was mit Arbeitsspeicher zu tun (ist aber nur ne Vermutung).

mit:
EXECUTE sp_OADestroy @Object
kann man das wohl lösen...

klappt auch.
Sind jetzt 800 Datensätze so durch gegangen.