0

Ich habe eine einfache gespeicherte Prozedur zum Auswählen, Formatieren und Kopieren von Datensätzen aus der TimeCard-Datenbank in unsere ERP-Datenbank. Beide sind SQL Server.Kopieren von Datensätzen mit gespeicherter Prozedur von SQL Server zu SQL Server (2005)

Es wird auf dem SQL Server-Agent als geplanter Job ausgeführt. Der Code sieht wie folgt nun

INSERT INTO linked_erpserver.db.SCHEMA.table01 
SELECT * 
FROM linked_timecardserver.db.SCHEMA.tablexx X 
WHERE X.flag = 0 

UPDATE linked_timecardserver.db.SCHEMA.tablexx 
SET flag = 1 
WHERE flag = 0 

, nehme an, wenn es eine große Anzahl von Datensätzen und den Anschluss an verknüpfte Server ausgefallen ist, wird es katastrophale Auswirkungen sein.

Wie kann ich damit umgehen? Soll ich Datensätze einzeln auswählen, diesen Datensatz einfügen, aktualisieren und festschreiben.

EDIT: Wir verwenden SQL Server 2005

+0

hi @rauf haben Sie den 'BEGIN TRAN' vor Ihren Transaktionen versucht? -> https://www.mssqltips.com/sqlservertutorial/3305/what-does-begin-tran-rollback-tran-and-commit-tran-mean/ –

+1

@AndyK nicht sicher, dass über verknüpfte Server funktionieren würde. Vielleicht verteilte Transaktion beginnen? – Eli

+0

@Rauf: Dieser Link könnte auch helfen: https: // stackoverflow.com/questions/506602/best-weg-zu-arbeiten-mit-transaktionen-in-ms-sql-server-management-studio Auch Senden an eine Staging-Tabelle und Überprüfen der Staging-Tabelle ist korrekt, bevor dann versuchen, es zu committen Ihr ERP würde Ihnen zusätzliches Vertrauen geben. – abraxascarab

Antwort

4

Verwenden Sie ein Distributed Transaction

Sie müssen Ihren Code in einer Transaktions einzuwickeln (alle/oder nichts) Einheit. Um dies zu unterstützen, muss der MSDTC-Dienst installiert, ausgeführt und möglicherweise auf beiden Windows/SQL-Servern konfiguriert werden. Dann müssen Sie die BEGIN DISTRIBUTED TRANSACTION T-SQL-Syntax verwenden. Ab SQL Server 2005 haben Sie die Magie, XACT_STATE zu verwenden, während wir früher nur XACT_ABORT hatten, das keine vollständige Lösung bot (nur fehlgeschlagene Schweregrade 16 oder höher).

XACT_STATE https://docs.microsoft.com/en-us/sql/t-sql/functions/xact-state-transact-sql

Aktualisiert: Hier ist der Code für SQL 2005-2017:

SET XACT_ABORT ON 
BEGIN DISTRIBUTED TRANSACTION; 
INSERT INTO linked_erpserver.db.SCHEMA.table01 

SELECT * 
FROM linked_timecardserver.db.SCHEMA.tablexx X 
WHERE X.flag = 0 

UPDATE linked_timecardserver.db.SCHEMA.tablexx 
SET flag = 1 
WHERE flag = 0 

IF (XACT_STATE()) < 0 ROLLBACK TRANSACTION 
--if XACT_STATE is 0, there is nothing to actually commit. 
IF (XACT_STATE()) = 1 COMMIT TRANSACTION; 

Hier ist ein Link, der zeigt, wie man die MS DTC-Konfiguration erhalten:

https://support.resolver.com/hc/en-ca/articles/207161116-Configure-Microsoft-Distributed-Transaction-Coordinator-MSDTC-

Hinweis: Anscheinend kann XACT_STATE eine -2 auch für Dinge wie eine Division durch Null Fehler zurückgeben - also die < 0 Rollback im obigen Code. Dies scheint nicht gut dokumentiert zu sein und lässt mich fragen, wie viele negative Werte XACT_STATE tatsächlich haben kann.

https://docs.microsoft.com/en-us/azure/sql-data-warehouse/sql-data-warehouse-develop-transactions

+0

Leider habe ich vergessen, die SQL Server-Version zu erwähnen. Wir verwenden immer noch SQL Server 2005 – Rauf

+0

Während die Online-Dokumentation nicht angezeigt, dass SQL 2005 XACT_STATE unterstützt, habe ich gerade überprüft, dass es in SQL 2005 über eine lokal installierte SQL 2005-Onlinedokumentation unterstützt wird. – Sting

+0

Wie kann ich überprüfen, ob der 'MSDTC Service' installiert ist? Leider haben wir keinen DBA, so dass ich keine zusätzliche Installation von "fromDB" und "toDB" möchte. Das heißt, ich benutze einen anderen PC mit SQL Server 2005, um Daten von Quell-DB zu Ziel-DB zu bekommen. – Rauf

1

Einfügen von Datensätzen einer nach dem anderen ist immer eine schlechte Praxis betrachtet, aber das gleiche gesagt werden könnte, wenn Sie Millionen von Datensätzen in einer einzigen select/insert.

Ich würde vorschlagen, einen Prozess zu erstellen, der n Datensätze gleichzeitig einfügt, während gleichzeitig alles in eine Transaktion eingewickelt wird, um sicherzustellen, dass entweder alle Datensätze in diesem Schritt aktualisiert werden oder im Fehlerfall keine aktualisiert werden .

DECLARE @NumRecords INT 
SELECT @NumRecords=COUNT(*) FROM Linked_TimeCardServer.DB.Schema.TableXX X 
WHERE X.FLAG = 0 

WHILE @NumRecords > 0 
BEGIN 
    BEGIN TRAN 

    -- Get 100 Records 
    SET ROWCOUNT 100 

    INSERT INTO Linked_ERPServer.DB.Schema.Table01 
    SELECT * FROM Linked_TimeCardServer.DB.Schema.TableXX X 
    WHERE X.FLAG = 0 

    If @@error <> 0 GOTO Error 

    -- Update the Records that were copied 
    SET ROWCOUNT 0 

    Update Linked_TimeCardServer.DB.Schema.TableXX 
    SET FLAG =1 
    WHERE PrimareyKeyColumnId NOT IN (
     SELECT PrimareyKeyColumnId FROM Linked_ERPServer.DB.Schema.Table01 
    ) 

    If @@error <> 0 GOTO Error 

    COMMIT TRAN 

    SELECT @NumRecords=COUNT(*) FROM Linked_TimeCardServer.DB.Schema.TableXX X 
    WHERE X.FLAG = 0 

END 

Error: 
    ROLLBACK TRAN 
Verwandte Themen