簡體   English   中英

您如何編寫遞歸存儲過程

[英]How do you write a recursive stored procedure

我只想要一個存儲過程,該過程計算一個唯一的ID(與標識列分開)並將其插入。 如果失敗,它會自行調用以重新生成所述ID。 我一直在尋找一個示例,但是找不到一個示例,並且不確定如何使SP調用自身並設置適當的輸出參數。 我也希望有人指出如何也測試此SP。

編輯

我現在想到的是以下內容(請注意,我已經有一個Identity列,我需要一個輔助ID列。

ALTER PROCEDURE [dbo].[DataInstance_Insert] 
    @DataContainerId int out,
    @ModelEntityId int,
    @ParentDataContainerId int, 
    @DataInstanceId int out
AS
BEGIN

    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    WHILE (@DataContainerId is null) 
        EXEC DataContainer_Insert @ModelEntityId, @ParentDataContainerId, @DataContainerId output   

    INSERT INTO DataInstance (DataContainerId, ModelEntityId)
    VALUES (@DataContainerId, @ModelEntityId)   

    SELECT @DataInstanceId = scope_identity()                       
END    

    ALTER PROCEDURE [dbo].[DataContainer_Insert]
        @ModelEntityId int,
        @ParentDataContainerId int,
        @DataContainerId int out
    AS
    BEGIN 
    BEGIN TRY
        SET NOCOUNT ON;
        DECLARE @ReferenceId int

        SELECT @ReferenceId = isnull(Max(ReferenceId)+1,1) from DataContainer Where ModelEntityId=@ModelEntityId

        INSERT INTO DataContainer (ReferenceId, ModelEntityId, ParentDataContainerId)
        VALUES (@ReferenceId, @ModelEntityId, @ParentDataContainerId)

        SELECT @DataContainerId = scope_identity()
    END TRY
    BEGIN CATCH
    END CATCH
    END
  1. 在CATCH塊中,您必須檢查XACT_STATE值。 您可能處於注定的事務(-1)中,在這種情況下,您將不得不回滾。 否則您的交易可能已經回滾,並且您不應該在現有交易的假設下繼續工作。 有關處理T-SQL異常的模板過程,請正確嘗試/捕獲blcoks和事務,請參閱異常處理和嵌套事務。
  2. 從不使用任何語言在異常塊中進行遞歸調用。 您無需檢查為什么會遇到異常,因此不知道是否可以重試。 如果例外是652只讀文件組,該怎么辦? 或者您的數據庫已達到最大大小? 您將重新進行詛咒,直到遇到stackoverflow ...
  3. 除非有適當的保護,否則讀取值的代碼,基於該值做出決定,然后寫入的代碼在並發性下總是會失敗。 您需要將SELECT和INSERT包裝在一個事務中,並且SELECT必須處於SERIALISABLE隔離級別下。

最后,忽略您帖子中公然錯誤的代碼,這是您如何調用傳遞OUTPUT參數的存儲過程的方法:

exec DataContainer_Insert  @SomeData, @DataContainerId OUTPUT;

為什么不使用:

 NewId() 

T SQL函數? (假設SQL Server 2005/2008)

更好的是,為什么不將UserID用作標識列,而不是嘗試手動重新實現標識列?

順便說一句:我想你的意思是

VALUES (@DataContainerId + 1 , SomeData)

該sp永遠不會成功插入,您在DataContainer表上具有一個identity屬性,但您正在插入ID,在這種情況下,您將需要設置identity_insert,但是scope_identity()將不起作用

PK沖突也可能不會被捕獲,因此您可能還需要檢查XACT_STATE()

你為什么要搞亂max,使用scope_identity()並完成它

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM