2013-02-11 68 views
0

早些時候,我創造了這個存儲過程:在插入前檢查重複項時是否需要事務?

  Create Procedure CreateEmployee 
      (
      @Role_ID Int, 
      @FirstName Varchar(50), 
      @LastName Varchar(50), 
      @DateOfBirth Varchar(50), 
      @Active Bit 
      ) 
      As 
      Begin 

      If Not Exists (Select FirstName, LastName, DateOfBirth 
       From Employee Where FirstName = @FirstName 
       AND LastName = @LastName 
       AND DateOfBirth = @DateOfBirth) 

       Begin 
       Insert Into Employee (Role_ID, FirstName, LastName, DateOfBirth, Active) 
       Values (@Role_ID, @FirstName, @LastName, @DateOfBirth, @Active) 
       End 

      Else 
       Begin 
       Select 'User already exists!' 
       End 

      End 

這個程序會檢查員工不已經在僱員表中存在執行插入之前。

看起來足以證明防彈,因爲它是在發生任何表改變之前完成的單個條件檢查。然而,在對交易進行一些閱讀之後,我想知道是否應該讓我所有的程序交易獲得額外的保護。

tl dr;有沒有什麼時候你不應該使用交易?

回答

1

我想知道是否應該讓我的所有程序交易 額外的一層保護。

絕對不是!如果你這樣做,你會使數據庫更有可能與deadlock,以及相關的性能問題。

有沒有什麼時候你不應該使用交易?

看看每個過程本身,只添加一個絕對必要的事務,確保事務塊儘可能小。另外,確保每個事務中的表訪問順序是相同的。這些提示將有助於解決死鎖和性能問題。

在這種情況下,如果您擔心有重複的客戶,請添加一個唯一的約束 - 您不需要在此處進行交易。

順便說一下,FirstName,LastName和DateOfBirth對於確定真正的客戶數據庫中的唯一性並不好。例如,約翰史密斯有兩個出生日期相當可能。

+0

與唯一性相關,如果非活動員工再次加入,上述SQL不會更改活動列。 – 2013-02-11 12:42:46

0

數據庫,如多線程程序,允許同時訪問讀取和修改數據。

在這種情況下你;

  1. 檢查一個特定的行不存在
  2. 插入

雖然每個語句是原子的,可在1和2之間發生的任何其它陳述/交易中,包括另一行插入同一行。

因此,爲了防止這種情況,您必須在兩個語句周圍使用事務來使其成爲一個原子動作。

如果執行檢查/修改序列的任何地方都需要事務包裝器(如果其影響是邏輯損壞的)。

0

首先,將一個UNIQUE約束添加到您的表(如果您還沒有)。那麼你可以只TRYINSERT,如果它是重複的,你會得到一個錯誤,你可以CATCH。這通常比預先檢查重複項更簡單,而且您不必擔心事務或死鎖。

相關問題