2009-11-11 180 views
0

當爲一個存儲過程調用多個存儲過程時,這是在SQL Server 2008上使用它的正確還是最好的方法?存儲過程調用多個存儲過程

CREATE PROCEDURE [dbo].[DoStuff] 
AS 
BEGIN 
    SET NOCOUNT ON; 
    declare @result int 
    BEGIN TRANSACTION 
     BEGIN 
      EXECUTE @result = dbo.UpdateTHIS @ID = 1    
      IF @result != 0 
       ROLLBACK 
      ELSE 
       EXECUTE @result = dbo.UpdateTHAT @ID = 21    
       IF @result != 0 
        ROLLBACK 
       ELSE 
        EXECUTE @result = dbo.UpdateANOTEHR @ID = 15 
        IF @result != 0 
         ROLLBACK 
        ELSE 
         COMMIT 
         SELECT @result 
     END    
END 
+2

看起來不錯,除了我會爲每個IF和ELSE – 2009-11-11 16:04:35

+0

r IFs嵌套?...如果他們r然後我寧願使用BEGIN和END在我們的邏輯寫他們... ...使用顯式BEGIN和END ... – deostroll 2009-11-11 16:06:55

回答

5

我強烈建議使用TRY/CATCH塊和RAISERROR而不是@@ ERROR/@結果檢查。我有一個博客條目,顯示如何正確使用交易和TRY/CATCH塊,包括嵌套事務以僅恢復失敗的過程調用工作,以便如果感覺如下:Exception Handling and Nested Transactions,則可以恢復不同的路徑並繼續交易。

<更新>

您現在的位置對於程序不一致的返回模式。 UpdateTHIS和UpdateTHAT返回0/1作爲返回值,而包裝DoStuff作爲結果集返回(SELECT)。這意味着您無法編寫調用DoStuff的DoMoreStuff,因爲它必須使用INSERT ... EXEC捕獲結果,並且您將很快發現INSERT ... EXEC無法嵌套。爲了保持一致性,我建議使用RETURN @result。

< /更新>

我也有一個不相關的表彰,這只是風格的元素:我覺得長IF ... ELSE IF ... ELSE IF ... ELSE IF ...塊難以閱讀和遵循。我總是發現,表達與DO相同... BREAK ... BREAK ... BREAK ... WHILE(FALSE)更容易閱讀。 T-SQL沒有DO ... WHILE結構,所以一段時間...有用於代替:

BEGIN TRANSACTION 
WHILE (1=1) 
BEGIN 
    EXECUTE @result = dbo.UpdateTHIS @ID = 1;   
    IF @result != 0 
    BEGIN 
    ROLLBACK; 
    BREAK; 
    END 

    EXECUTE @result = dbo.UpdateTHAT @ID = 21    
    IF @result != 0 
    BEGIN 
    ROLLBACK; 
    BREAK; 
    END 

    ... 

    COMMIT; 
    BREAK; 
END 

同樣,這也不重要,因爲僅僅是一個代碼格式化的風格,但它是一個如果您同意這會導致代碼更容易閱讀,那麼建議您。

-1

恕我直言,我不認爲從一個存儲過程調用其他存儲過程是一個非常好的主意。如果出現錯誤,需要花費大量的人工時間才能找出錯誤發生的位置。在某些情況下,另一個開發人員可能會更改存儲的proc而不告訴團隊中的任何人。可能出錯的事情太多了。

可能最好將所有的sql寫入一個大的存儲過程。

編輯: 這也取決於你的存儲過程將會有多大。

+2

但費用是多少?在重構爲多個存儲過程之後,我維護一次的數千行存儲過程被削減爲一行或兩百行代碼。使存儲過程獨立存在會大大增加在存儲過程中發現的重複代碼量。 – MatthewMartin 2009-11-11 16:11:40

+0

的確,我不得不同意它取決於存儲過程的大小。 – iJK 2009-11-11 16:18:17

+0

我完全不同意。重複在多個存儲過程中執行相同操作的代碼將是一種不好的編程習慣。存儲過程專門用於封裝業務或數據邏輯,以便可以重用。 雖然從另一個層次調用存儲過程存在一些限制,但維護的好處大大超出了風險。就像應用程序中的任何「共享」組件(如DLL或Web服務等)一樣,更改後的兼容性是一個重要問題,但它遠不是一個大問題...... – JFTxJ 2013-09-16 14:06:11

1

嵌套ifs和不嵌套ifs不同。回滾將回滾一個事務,但繼續。我有一些明確的RETURN命令來保證,並明確何時何地你想讓代碼退出存儲過程。