2015-05-10 27 views
0

我有這樣的SQL Server存儲過程:SQL找回錯@@身份

CREATE procedure [dbo].[sp_FinancialInstitutionsAdd] 
    @Name varchar(50) 
AS 
    set nocount on 

    begin tran 
     declare @retval int = 0 
     declare @rmdID int 

     execute @rmdID = dbo.sp_MetaDataRecsAdd 

     select @rmdID as rmdID 

     if @@ERROR <> 0 
     begin 
      rollback tran 
      return -1 
     end 

     insert FinancialInstitutions (Name, rmdID) 
     values (@Name, @rmdID) 

     if @@ERROR <> 0 
     begin 
      rollback tran 
      return -1 
     end 

     return scope_identity() 
     commit tran 

我只能拿回插入MetaDataRecs表的ID,但我想FinacialInstitutions表的ID。該過程在SQL中直接執行時可以正常工作,但在執行代碼中的ExecuteScalar命令時不會執行。

+2

備註:您應該**不要**爲存儲過程使用'sp_'前綴。微軟已經保留了這個前綴以供自己使用(參見*命名存儲過程*)](http://msdn.microsoft.com/en-us/library/ms190669%28v=sql.105%29.aspx),以及你將來有可能冒着名字衝突的風險。 [這對你的存儲過程性能也是不利的](http://www.sqlperformance.com/2012/10/t-sql-queries/sp_prefix)。最好只是簡單地避免使用'sp_'並使用別的東西作爲前綴 - 或者根本沒有前綴! –

回答

-2

@@ identity和scope_identity()都會返回您創建的最後一個id。 對於使用將某些東西插入另一個表中的觸發器的人來說,這也是一個問題。

我不知道你的表,但我會做這樣的事情

declare @id int 
select @id = max(id) from FinancialInstitutions 
return @id 

歡呼

+1

Downvote原因:這個答案是錯誤的。 Scope_identity()將返回其執行範圍中的最後一個標識。如果它在存儲過程中執行,它將不會返回由觸發器創建的標識。 [read here](http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/) –

+0

Did你在downvoting之前試用它? –

+1

*您是否?* 閱讀我已鏈接的文章。有一個原因叫做scope_identity()。 –

1

首先,除非你使用一個很老的SQL Server版本,您應該使用Try...catch而不是舊的風格if @@ERROR <> 0。 Sql server自2005年以來支持Try ... catch。
其次,我懷疑你從scope_identity()函數中得到錯誤的身份,因爲它沒有被包含在事務中。如果事務回滾,我不確定它應該返回什麼。
試試這個:

CREATE procedure [dbo].[sp_FinancialInstitutionsAdd] 
(
    @Name varchar(50), 
    @ReturnValue int output 
) 
AS 
set nocount on 

declare @rmdID int, 
     @retval int = 0 

begin Try 
    begin tran 

    execute @rmdID = dbo.sp_MetaDataRecsAdd 

    -- select @rmdID as rmdID -- What is that row? I've commented it out since it makes no sense to me 

    insert into FinancialInstitutions (Name ,rmdID) 
    values (@Name ,@rmdID) 

    set @ReturnValue = scope_identity() 
    commit tran 
end try 
begin catch 
    rollback tran 
end catch 

注#1:您需要將您的通話切換到該程序的@ReturnValue添加作爲輸出參數。

注意2:如果此過程將這一行set @ReturnValue = scope_identity()之前遇到錯誤的@ReturnValue值將保持DBNull.Value

+0

當這個過程從sql查詢運行時,它工作正常。當它與executecalar一起運行時,它將返回null。 (但表更新發生。) – kunstena

+0

這是因爲['ExecuteScalar'](https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar%28v=vs.110%29 .aspx)不會返回過程的返回值,而是返回select語句的第一個值或行。您的程序中沒有選擇語句。看到我編輯的答案。 –

+0

替換set @ReturnValue = scope_identity() – kunstena

-1
  1. 根據我的理解,您依靠舊的方法來處理錯誤。 嘗試使用TRY..CATCH塊來提高可讀性和良好的實踐設計。

  2. 也不要使用RETURN將標識值返回給調用者,最好的做法是爲此目的聲明OUTPUT參數。

+0

downvote原因:這個答案沒有添加任何我沒有在我的回答中提到的信息,在你發佈你的信息之前6個小時。 –