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。这通常比预先检查重复项更简单,而且您不必担心事务或死锁。

相关问题