2014-07-05 27 views
0

需要關於下面的存儲過程的建議以避免併發問題。使用開始提交回退避免併發返回語句和UPDLOCK,HOLDLOCK

Create PROCEDURE [SD_SaveUpdate_DepartmentDetails]       
@DeptID int, 
@DepartmentName varchar(100), 
@DepartmentID int out 

AS        
BEGIN 
Begin Try 

-------------------------Insert Update Department Details-----------------------  

Begin 

SET NOCOUNT ON 

BEGIN TRAN Department 

IF EXISTS(SELECT * FROM DepartmentTable WITH (UPDLOCK, HOLDLOCK) WHERE DepartmentName= @DepartmentName) 
BEGIN 
     UPDATE DepartmentTable SET DepartmentName= @DepartmentName WHERE DeptID = @DeptID 
     set @[email protected] 
END 
ELSE 
BEGIN 
     INSERT INTO DepartmentTable (DepartmentName) VALUES (@DepartmentName) 
     set @[email protected]@IDentity 
END 

COMMIT Transaction Department 
End 
-------------------------Insert Update Department Details-----------------------  
End Try 
Begin Catch 
set @DepartmentID=0 
End Catch 

End 

是我上面的方法使用(UPDLOCK,HOLDLOCK)正確。

我想設置@DepartmentID輸出參數=「-1」,如果部門沒有爲USER2保存,因爲它是重複的。我需要在上面的SP中添加set @ DepartmentID = -1行。

在catch塊我設置@ DepartmentID = 0,如果有一些錯誤,同時保存。但我也想設置@ DepartmentID = -1時重複occcurs。

在博客的其中一篇博文中,我看到使用HOLDLOCK以避免併發症的使用。我想知道其他用戶是否可以在SP運行時訪問(選擇)數據。

你可以請這個SP以及optimitic幫助我(成本效益),以便我可以在所有存儲過程中使用相同的邏輯。

謝謝,

Prathap。

+1

你可以有一個唯一約束/索引重複這個問題混合多種不同的擔​​憂在一起:用戶界面,併發和T-SQL邏輯。一次問一件事。例如,我沒有看到用戶界面與這個問題有什麼關係。從這個問題中刪除所有UI的東西。目前的形式不值得回答。 – usr

+0

我試圖更清楚我需要什麼..編輯我的問題 – user2859242

+0

如果2005有'MERGE',那對你來說是更好的選擇。 –

回答

0

謝謝大家使用鎖定概念time.Without(SET事務隔離級別)或任何UPDLOCK,我想下面的SP

Create PROCEDURE [SD_SaveUpdate_DepartmentDetails]       
@DeptID int, 
@DepartmentName varchar(100), 
@DepartmentID int out 


AS        
BEGIN 
Begin Try 

-------------------------Insert Update Department Details-----------------------  

Begin 

SET NOCOUNT ON 

BEGIN TRAN Department 

IF Not EXISTS(SELECT Top 1 DepartmentName FROM DepartmentTable WHERE DepartmentName= @DepartmentName 
    and Isdeleted=0 and DeptID <> @DeptID) 
and @DeptID > 0 
BEGIN 
     UPDATE DepartmentTable SET DepartmentName= @DepartmentName,lastupdated=getdate() WHERE DeptID = @DeptID 
     set @DepartmentID = @DeptID 
END 
ELSE IF NOT EXISTS(SELECT Top 1 DepartmentName FROM DepartmentTable WHERE DepartmentName= @DepartmentName and IsDeleted=0) 
and @DeptID=0 
BEGIN 
     INSERT INTO DepartmentTable (DepartmentName,isdeleted,lastupdated) VALUES (@DepartmentName,0,getdate()) 
     set @DepartmentID=Scope_IDentity() 
END 
Else 
Begin 
set @DepartmentID = -1 
End 

COMMIT Transaction Department 
End 
-------------------------Insert Update Department Details-----------------------  
End Try 
Begin Catch 
set @DepartmentID = 0 
End Catch 
End 

要確認是否有重複的值,我使用SQLQUERYSTRESS工具爲多用戶場景(併發)及其成功測試了此SP。沒有重複的值。

如果有任何建議,請讓我知道。

0

你爲什麼要實現所有這些複雜的併發性的東西?

而且從不使用@@IDENTITY,總是使用scope_identity()

我想設置@DepartmentID輸出paramater =「1」,如果該部門未保存爲USER2,因爲它的一個duplicate.Where做我需要在上面的SP中添加set @ DepartmentID = -1行。

做什麼類似下面的問題 - 爲什麼你需要鎖定表?

-- This will insert a record if it doesn't already exist 
-- If it does already exist it won't insert a record 
INSERT INTO DepartmentTable (DeptID) 
SELECT DeptID WHERE NOT EXISTS (
    SELECT 1 FROM DepartmentTable WHERE DeptID = @DeptID 

-- find the new ID. This is NULL if no record was inserted 
SELECT @DepartmentID=SCOPE_IDENTITY() 

-- If no row was inserted, this was a duplicate and scope_identity is null 
IF @DepartmentID IS NULL SET @DepartmentID = -1 
+0

感謝您的建議將使用scope_identity()。對不起,我編輯的問題DeptID是主鍵,我需要檢查部門名稱重複。在您的SP如果十個用戶正在訪問SP並插入相同的部門名稱,是不是有重複的機會。我不喜歡使用鎖,並希望我的SP更加簡單而有效。 – user2859242

+0

爲什麼不對部門名稱設置唯一的限制。那麼沒有人可以插入重複的部門名稱。 –

+0

唯一約束在我的方案中無效,因爲如果DepartmentName是刪除,那麼我正在更新IsDeleted = 1。我已經添加了一個答案。可以請你提出任何改進建議。 – user2859242

0

你看了Merge聲明嗎?我認爲Merge會是一個更好的方法。爲了避免對departmentname

CREATE PROCEDURE [SD_SaveUpdate_DepartmentDetails]       
@depatid int, 
@DepartmentName varchar(100) 
AS        
BEGIN 
Begin Try 

-------------------------Insert Update Department Details-----------------------  

Begin  
SET NOCOUNT ON 
BEGIN TRAN Department  

MERGE DepartmentTable TGT 
USING 
(SELECT @departmentname deptname, @departmentid deptid) as SRC 
ON TGT.DEPTID=SRC.DEPTID 
WHEN MATCHED THEN 
    UPDATE 
    SET DepartmentName= @DepartmentName,lastupdated=getdate() 
WHEN NOT MATCHED THEN 
    INSERT VALUES(@DepartmentName,0,getdate()) 

OUTPUT case when $action='INSERT' then DELETED.DEPTID ELSE Inserted.deptid end 
+0

合併在SQL 2005中不可用... – user2859242