2010-04-21 116 views
5

我有自己爲了調用其他存儲過程的列表存儲過程:存儲過程 - 強制執行順序

CREATE PROCEDURE [dbo].[prSuperProc] 

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

不過,有時我在我的表,由prProc2,產生了一些奇怪的結果,其取決於prProc1生成的結果。如果我手動執行prProc1,prProc2,prProc3,那麼一切都很好。看來,當我運行頂層過程時,Proc2在Proc1完成並將其結果提交給數據庫之前正在執行。它並不總是出錯,但當Proc1執行時間很長(在這種情況下大約爲10s)時似乎出錯了。

如何修改prSuperProc,使每個過程只在前面的過程完成並提交後才執行?交易?

編輯額外的細節:

有一個在我的數據庫表具有列其默認爲空。 prProc1在此表上執行一組更新語句來填充此列。然後prProc2根據此列中的值將摘要數據插入輔助表中。

當我運行超級過程時,我(有時)看到的是第一個表具有由prProc1正確計算的結果,但是prProc2已生成結果,就好像列全部爲空。如果我然後手動運行prProc2,則會正確生成摘要數據。

回答

4

Proc2將不是 Proc1之前運行:這是一個簡單的。 SQL將依次執行,但絕不會出現故障。

您可以使用配置文件這個TSQL_SPs template

你有2個處決包裝PROC運行,例如?

+1

我確定包裝過程只能在任何時候運行一次 - 目前只有我使用過! 我並不是說他們的程序運行不正常,只是在Proc2啓動時Proc1所執行的更新沒有完全提交,而我已經通過手動執行它們來刪除該錯誤,從而證實了這一點。 – meepmeep 2010-04-21 13:14:37

+0

@meepmeep,在所有這些過程(包括包裝)中添加'PRINT'開始prProc1''和'PRINT'結束prProc1''類型語句,然後在SSMS中運行'EXEC [dbo]。[prSuperProc]',帶參數所以Proc1有很長的執行時間(在這種情況下大約10s)來查看會發生什麼。 – 2010-04-21 13:18:26

+0

我已經把它放進去了。一如往常,這個錯誤拒絕再次發生,所以我會把這個Q打開,直到它再次發生,看看結果如何。謝謝! – meepmeep 2010-04-22 09:12:39

2

對於每個呼叫prSuperProc,它們將以串行方式運行,然後是1,然後是下一個,然後是下一個。但是,如果多個用戶都呼叫prSuperProc,那麼您將交叉執行用戶1的prProc1-prProc2 + prProc3和用戶2的prProc1-prProc2 + prProc3。

這可能是這樣的:

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 

它實際上取決於是怎麼回事你的程序,有多少併發用戶,什麼行內對它們進行改變和/或鎖定

編輯 你可以試試這個來解決這個問題:通過使用交易

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 

ñ圍繞一切,它將嘗試鎖定任何併發用戶使用相同的數據。使用TRY-CATCH將嘗試捕捉一個過程中可能發生的任何錯誤,並阻止下一個過程運行。

1

我有同樣的問題(當時正在維護產品),我通過取出最外面的proc並執行最上面的proc來修復它。然後該proc將執行依賴於它的proc等。它在B ***的痛苦,但它的作品。

HTH

+0

謝謝 - 我要去嘗試下面的交易,但如果失敗了,那麼這是一個非優雅的解決方案。我希望能夠獨立運行proc,所以我需要添加一些通過proc調用級聯的參數。 – meepmeep 2010-04-21 15:55:27