2010-04-21 18 views
5

Ich habe eine gespeicherte Prozedur, die selbst eine Liste von anderen gespeicherten Prozeduren, um Anrufe:Stored Procedure - Zwingen Ausführungsreihenfolge

CREATE PROCEDURE [dbo].[prSuperProc] 

AS 
BEGIN 
    EXEC [dbo].[prProc1] 
    EXEC [dbo].[prProc2] 
    EXEC [dbo].[prProc3] 
    --etc 
END 

Allerdings habe ich manchmal einige seltsame Ergebnisse in meine Tabellen haben, von prProc2 erzeugt, die hängt von den Ergebnissen ab, die von prProc1 generiert werden. Wenn ich prProc1, prProc2, prProc3 in der Reihenfolge manuell ausführe, dann ist alles in Ordnung. Es scheint, dass, wenn ich die Top-Level-Prozedur ausführen, Proc2 ausgeführt wird, bevor Proc1 abgeschlossen und seine Ergebnisse an die Datenbank übergeben hat. Es geht nicht immer schief, aber es scheint falsch zu laufen, wenn Proc1 eine lange Ausführungszeit hat (in diesem Fall ~ 10s).

Wie ändere ich prSuperProc so, dass jede Prozedur nur ausgeführt wird, wenn die vorhergehende Prozedur abgeschlossen und festgeschrieben wurde? Transaktionen?

bearbeiten extra Detail:

Es gibt einen Tisch in meinem db, die eine Spalte hat, die standardmäßig null ist. prProc1 führt eine Reihe von update-Anweisungen für diese Tabelle aus, um diese Spalte aufzufüllen. prProc2 fügt dann zusammenfassende Daten in eine sekundäre Tabelle basierend auf den Werten in dieser Spalte ein.

Wenn ich die Super-Prozedur ausführen, was ich (manchmal) sehe, ist die erste Tabelle hat die Ergebnisse korrekt von PrProc1 berechnet, aber PrProc2 hat Ergebnisse erzeugt, als ob die Spalte alle Nullen war. Wenn ich dann prProc2 manuell ausführe, werden die Zusammenfassungsdaten korrekt generiert.

Antwort

4

Proc2 wird nicht vor Proc1 laufen: es ist so einfach. SQL wird nacheinander ausgeführt, aber nie außer Betrieb.

Sie können dies die TSQL_SPs template

Sie mit Profil, das Sie zwei Ausführungen der Wrapper proc läuft, zum Beispiel?

+1

Ich bin sicher, dass der Wrapper proc nur jederzeit einmal ausgeführt - es nur von mir zur Zeit verwendet wird! Ich schlage nicht vor, dass sie außer Betrieb sind, nur dass die von Proc1 durchgeführten Updates nicht vollständig festgeschrieben werden, wenn Proc2 startet, und ich habe dies bestätigt, indem ich sie manuell ausgeführt habe, um den Fehler zu entfernen. – meepmeep

+0

@meepmeep, füge 'PRINT 'hinzu, starte prProc1'' und' PRINT' und beende alle prProc1''-Anweisungen in all diesen Prozeduren (einschließlich des Wrappers) und führe dann in SSMS 'EXEC [dbo]. [PrSuperProc]' mit Parametern aus Proc1 hat also eine lange Ausführungszeit (in diesem Fall ~ 10s), um zu sehen, was passiert. –

+0

Ich habe das hier eingefügt. Wie immer weigert sich der Bug zu wiederholen, also lasse ich dieses Q offen, bis es wieder passiert und sehe was passiert. Vielen Dank! – meepmeep

2

Bei jedem Anruf von prSuperProc werden sie seriell ausgeführt, 1 dann der nächste, dann der nächste. Wenn jedoch mehrere Benutzer alle prSuperProc aufrufen, haben Sie eine verschachtelte Ausführung von prProc1-prProc2 + prProc3 von Benutzer 1 und prProc1-prProc2 + prProc3 von Benutzer 2.

, die so etwas wie dies sein könnte:

user1 calls prSuperProc 
user1   prProc1 is called 
user2 calls prSuperProc 
user1   prProc2 is called 
user2   prProc1 is called 
user1   prProc3 is called 
user2   prProc2 is called 
user2   prProc3 is called 

es hängt davon ab, was wirklich in Ihrem Verfahren vor sich geht, wie viele Benutzer gleichzeitig, und welche Reihen sie sich verändern und/oder Verriegelungs

EDIT können Sie dies versuchen, das Problem zu beheben:

CREATE PROCEDURE [dbo].[prSuperProc] 

AS 
BEGIN TRY 
    BEGIN TRANSACTION 
    EXEC [dbo].[prProc1] 
    EXEC [dbo].[prProc2] 
    EXEC [dbo].[prProc3] 
    --etc 
    COMMIT 
END TRY 
BEGIN CATCH 
    IF XACT_STATE()!=0 
    BEGIN 
     ROLLBACK TRANSACTION 
    END 

    SELECT 
     ERROR_NUMBER() AS ErrorNumber 
     ,ERROR_SEVERITY() AS ErrorSeverity 
     ,ERROR_STATE() AS ErrorState 
     ,ERROR_PROCEDURE() AS ErrorProcedure 
     ,ERROR_LINE() AS ErrorLine 
     ,ERROR_MESSAGE() AS ErrorMessage 


    --will echo back the complete original error message 
    DECLARE @ErrorMessage nvarchar(400), @ErrorNumber int, @ErrorSeverity int, @ErrorState int, @ErrorLine int 
    SELECT @ErrorMessage = N'Error %d, Line %d, Message: '+ERROR_MESSAGE(),@ErrorNumber = ERROR_NUMBER(),@ErrorSeverity = ERROR_SEVERITY(),@ErrorState = ERROR_STATE(),@ErrorLine = ERROR_LINE() 
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine) 

END CATCH 
GO 

durch eine transactio mit Um alles herum wird es versuchen, alle gleichzeitigen Benutzer daran zu hindern, an den gleichen Daten zu arbeiten. Die Verwendung des TRY-CATCH versucht, alle Fehler zu erfassen, die in einer Prozedur auftreten können, und zu verhindern, dass die nächsten ausgeführt werden.

1

Ich hatte das gleiche Problem (war ein Produkt zu dieser Zeit zu pflegen) und ich reparierte es, indem ich das äußerste proc herausnahm und das höchst proc ausführte. Dann würde dieser Proc den davon abhängigen Proc ausführen und so weiter. Es ist ein Schmerz in der B ***, aber es funktioniert.

HTH

+0

danke - Ich werde die Transaktionen unten versuchen, aber wenn das scheitert dann funktioniert dies als eine nicht elegante Lösung. Ich möchte in der Lage sein, die Procs auch unabhängig auszuführen, also muss ich einen Parameter hinzufügen, der die Proc-Aufrufe durchläuft. – meepmeep