Aufruf Store Procedure über sqlcmd getriggert über den Aufgabenplaner

macke384

Neuer Benutzer
Beiträge
3
Hallo zusammen,
ich bin am verzweifeln. Ich habe eine Store Procedure, die über einen MSXML2.ServerXMLHTTP Aufruf REST-API Daten ( JSON) File abholt. Wenn ich diese jetzt normal über SSMS aufrufe und starte funktiniert diese ohne Probleme. Der Aufruf holt sich die JSON Daten ab und stellt Sie in einer Tabelle zur Verfügung. Wenn ich nun die SP über ein Batchfile (wird auch von der Aufgaben planer aufgerufen) sqlcmd -S localhost -d DBname -E -Q "EXEC [dbo].[usp_get_API]" aufrufe. gibt es zwei zustände. Wenn der zurückgelieferte JSON String kleiner 2048 Byte ist ist alles OK. Wenn er größer ist schneidet er bei 2048 Bytes ab und dadurch der JSON String ungültig. Die Tabelle in der der AUfruf schreib ist als DECLARE @json AS TABLE(Json_Table NVARCHAR(MAX)); angelegt. Wie gesagt das Fehlerbild kommt nur wenn die SP über SQLCMD aufgerufen wird. Es wird natürlich der gleich e User benutzt.
[
EXEC @ret = sp_OAMethod @token, 'open', NULL, 'GET', @url1, 'false';
EXEC @ret = sp_OAMethod @token,'setRequestHeader', NULL, 'Content-type', @contentType ;
EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'Authorization', @bearer;
EXEC @ret = sp_OAMethod @token, 'send', null;

-- Handle the response
exec @ret = sp_OAGetProperty @token, 'status', @status out;
INSERT into @json (Json_Table) EXEC sp_OAGetProperty @token, 'responseText';
]
Rechte sind soweit alle gesetzt.
Vielleicht hat jemand eine Idee wo ich noch ansetzen könnte.
LG
Michael
 
Werbung:
Bei Aufruf über "Aufgaben Planer" könnte ein Problem liegen.
Gibt's es Fehlermeldungen? Gibt es Fehlerereignisse in der Ereignisliste?

Der Aufgaben Planer läuft idR als Dienst mit einem eigenen Rechtekontext. Der Dienst oder ab einem bestimmten Zeitpunkt die Commands brauchen also bestimmte Rechte (letztlich die gleichen, wie Du sie interaktiv nutzt).
Wenn dabei Dateien geschrieben werden (Gepuffert?, ..), gilt das auch für Dateien (Schreib-/ Leserechte)

Warum der Fehler dabei genau so geschieht, ist nur anhand der Aufrufe die Du zeigst schwer nachvollziehbar.
Notfalls kannst Du Log Operationen in Deine SP einbauen und anhand der Ausgabe nachvollziehen, ab wann abgeschnitten wird.
 
Danke für die Antwort. Letztendlich wird bei einem remote Aufruf der 'responseText' bei ca 2048 Bytes abgeschnitten, obwohl ich die Variable ja mit NVARCHAR(MAX) declariert habe. wenn ich remote Aufrufe liefert sp_OAGetProperty nur 2048 Zeichen zurück. Wenn ich die Procedure normal aufrufe (von Hand über SSMS starte)kommen alle Zeichen...
Es ist wirklich zum Verzweifeln.
 
Hallo dabadepdu,

hier die komplette Procedure. Der Fehler passiert wie geschrieben nach dem INSERT into @json (Json_Table) EXEC sp_OAGetProperty @token, 'responseText';. Wenn ich die SP direkt auf rufe ist alles fein. Beim Aufruf über den Aufgabenplaner bzw. auch in der CMD passiert der Fehler, dass abgeschnitten wird.

[
-- Variable declaration related to the Object.
DECLARE @token INT;
DECLARE @ret INT;
declare @status nvarchar(32);
declare @statusText nvarchar(32);
declare @readystate nvarchar(32);
-- Variable declaration related to the Request.
DECLARE @url NVARCHAR(1024);
DECLARE @url1 NVARCHAR(MAX);
DECLARE @Json2 NVARCHAR(MAX);
DECLARE @fields NVARCHAR(MAX);
DECLARE @authHeader NVARCHAR(64);
DECLARE @contentType NVARCHAR(64);
DECLARE @body NVARCHAR(256);
DECLARE @apiKey NVARCHAR(32);
DECLARE @bearer NVARCHAR(256);
DECLARE @bearer_date DATETIME;

-- Variable declaration related to the JSON string.
DECLARE @json AS TABLE(Json_Table NVARCHAR(MAX));

-- Variablen für die Abholung
DECLARE @offset INT;
DECLARE @limit INT;
DECLARE @max_ticket INT;
DECLARE @offset_diff int;
DECLARE @last_ticket DATETIME2;
DECLARE @last_run DATETIME2;
DECLARE @last_run_st NVARCHAR(50);
DECLARE @new_run DATETIME2;
DECLARE @akt_time DATETIME2;
DECLARE @first BIT;
DECLARE @last BIT;
DECLARE @t_ende INT;
DECLARE @t_ende_max INT;

SET @ret = 0
INSERT INTO dbo.api_log (Log_time, Log_Error, Log_Aktion)
VALUES (GETDATE(), @ret, 'get_ticket_Start');

SET @offset_diff = 20;
SET @limit = @offset_diff;
SET @offset = 0;
SET @first = 'false'; -- false = 0 / true =1
SET @last = 'false';

-- Define the URL and more
SET @url = (SELECT a_abfrage_p1 FROM api_daten WHERE a_abfrage = 'PROD_TICKET');
SET @fields = (SELECT a_abfrage_p2 FROM api_daten WHERE a_abfrage = 'PROD_TICKET');
SET @bearer = 'Bearer ' + (SELECT a_tok FROM api_daten WHERE a_abfrage = 'PROD_TOKEN');
SET @last_ticket = (SELECT a_token_time FROM api_daten WHERE a_abfrage = 'PROD_TOKEN');
SET @last_run = (SELECT a_lastrun FROM api_daten WHERE a_abfrage = 'PROD_TICKET');
SET @new_run = GETUTCDATE();
--Umgeungslösung, da der Convert bei.000 ms keinen Wert liefert!
SET @last_run_st = LEFT(CONVERT(NVARCHAR, @last_run, 126),19) + '.000Z';


--Neuer Token für login abholen und überprüfen
EXEC usp_post_token;
SET @ret = 0;
INSERT INTO dbo.api_log (Log_time, Log_Error, Log_Aktion)
VALUES (GETDATE(), @ret, 'Get_Ticket_post_token');

SET @contentType = 'application/json';

-- This creates the new object.
EXEC @ret = sp_OACreate 'MSXML2.ServerXMLHTTP', @token OUT;
IF @ret <> 0
BEGIN
RAISERROR('Unable to open HTTP connection.', 10, 1);
SET @last = 'true';
INSERT INTO dbo.api_log (Log_time, Log_Error, Log_Aktion)
VALUES (GETDATE(), @ret, 'Get_Ticket_Unable to open HTTP connection.');
SET @ret = 99999;
END;

While @last = 'false'
BEGIN
-- mit
SET @url1 = @url + 'offset=' + LTRIM(STR(@offset,10)) + '&limit=' + LTRIM(STR(@limit,10)) + '&changedSince=' + @last_run_st + '&fields=' + @fields;

--SET @url1 = @url + 'offset=' + LTRIM(STR(@offset,10)) + '&limit=' + LTRIM(STR(@limit,10)) + '&fields=' + @fields;
-- This calls the necessary methods.
EXEC @ret = sp_OAMethod @token, 'open', NULL, 'GET', @url1, 'false';

EXEC @ret = sp_OAMethod @token,'setRequestHeader', NULL, 'Content-type', @contentType ;
EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'Authorization', @bearer;
EXEC @ret = sp_OAMethod @token, 'send', null;

-- Handle the response
exec @ret = sp_OAGetProperty @token, 'status', @status out;
exec @ret = sp_OAGetProperty @token, 'statusText', @statusText out;
exec @ret = sp_OAGetProperty @token, 'ReadyState', @readystate out;
-- Grab the responseText property, and insert the JSON string into a table temporarily. This is very important, if you don't do this step you'll run into problems.

INSERT into @json (Json_Table) EXEC sp_OAGetProperty @token, 'responseText';
--PRINT @json2;
--PRINT @status;
--PRINT @statusText;

IF @status = 200
BEGIN
--SELECT * FROM @Json;
SELECT @json2 = Json_Table FROM @Json; -- Hier passiert der Fehler!
print @json2;
print LEN(@json2);
SET @ret = 0;
-- wenn alles gut gegangen ist.........

IF @first = 'false'
BEGIN
-- Maximale Anzahl Tickets ermitteln
SELECT @t_ende_max = [value] FROM OPENJSON((SELECT * FROM @json)) Where [KEY]= 'totalCount';
SET @first = 'true';
SET @t_ende = @offset + @offset_diff;
INSERT INTO dbo.api_log (Log_time, Log_Error, Log_Aktion)
VALUES (GETDATE(), @t_ende_max, 'Anzahl_Ticket_Max');
-- Wenn keine Ticket zum abholen sind.
IF @t_ende_max = 0
BEGIN
set @last = 'true';
END;
END;
ELSE
BEGIN
SET @t_ende = @offset_diff;
IF (@t_ende_max - @offset) < @offset_diff
BEGIN
SET @t_ende = @t_ende_max - @offset;
SET @last = 'true';
END;
END;

-- Ab hier werden die Tabellen mit den JSON Daten gefüllt
SELECT @json2 = [value] FROM OPENJSON((SELECT * FROM @json )) Where [KEY]= 'ticket' ;
--PRINT @json2;
DELETE FROM @json;
IF (ISJSON(@json2) > 0 AND @t_ende_max > 0)
BEGIN
--Aufruf Procedure zum schreiben der Daten
--ticket
EXEC @ret = usp_update_ticket @json2;
INSERT INTO dbo.api_log (Log_time, Log_Error, Log_Aktion)
VALUES (GETDATE(), @ret, 'Get_Ticket_Update_ticket');
--docBeeDocuments


END

--SELECT * FROM ticket;


END;
ELSE
BEGIN
SET @ret = 99999;
-- Wenn etwas schieft geht schleife beenden........
SET @last = 'true';
END;


SET @offset = @offset + @offset_diff;
END;

IF @ret = 99999
BEGIN

INSERT INTO dbo.api_log (Log_time, Log_Error, Log_Aktion)
VALUES (GETDATE(), @ret, 'Get_Ticket_Ende_ERROR');
END
ELSE
BEGIN
SET @ret = 0;
UPDATE dbo.api_daten SET a_lastrun = @new_run WHERE a_abfrage = 'PROD_TICKET';
INSERT INTO dbo.api_log (Log_time, Log_Error, Log_Aktion)
VALUES (GETDATE(), @ret, 'Get_Ticket_Ende');


END;
Exec sp_OADestroy @token;

RETURN @ret;
GO
]

Gruß
Michael
 
Hm, ok, nicht sehr übersichtlich. Warum diese JSON & JSON2 Nummer?
Ich habe irgendwo gelesen, dass das Ergebnis in eine Tabelle geschrieben werden soll(te), (statt variable) um das Problem zu umgehen. Finde ich leider nicht mehr.
Ich habe auch irgendwo gelesen, dass die SP_0A Funktionen sehr buggy sind und nicht genutzt werden sollten (nur aus Kompatibilitätsgründen existieren - woraus man lesen könnte, dass sie auch nicht mehr korrigiert werden).

Mehr kann ich dazu nicht sagen, ich nutze MS SQL nicht aktiv und hätte nicht mal die Möglichkeit, es nachzuvollziehen.
 
Hm, Du schreibst im SSMS als normaler Aufruf funktioniert das ganze. Warum willst du das dann unbedingt als Batch bzw. über sqlcmd aufrufen? Oder meinst Du mit "Aufgabenplaner" etwa den Task Scheduler von Windows? Dabei wäre doch der SQL Server Agent für sowas viel besser geeignet
 
Eventuell SQLEXPRESS, das hat keinen Server Agent wenn ich das richtig in Erinnerung habe.

Häufigste Ursache für Probleme beim Ausführen von SQL Code aus der CMD sind vermutlich Rechte, aber die SP scheint ja zu starten, dann müsste sie eigentlich auch laufen.
 
Werbung:
Zurück
Oben