Sql-Server

如果在更新或刪除之前存在?

  • September 30, 2017
  1. 在我寫一個更新語句之前,我應該檢查它是否存在?

有人告訴我這樣做

  1. 因此它避免了無用地寫入事務日誌以獲取已經存在的值,
  2. 並且只需要一個允許其他讀取的共享鎖而不是排他鎖。

他們說想像一個事務像這樣針對不同的值多次執行,你將一直使用排他鎖而不是共享鎖。 3. 同事提到,看鎖兼容性圖表,搜尋時不能有兩個更新鎖,但是可以有兩個共享鎖。因此,當“搜尋要更新的行”沒有要更新的值時,虛假的更新鎖可能會阻止真正的更新。有人可以使此聲明無效嗎?

if not exists 
(
    select FavoriteColor 
    from dbo.Person 
    where Name = 'Bob' 
    and FavoriteColor = 'Green'
)
update dbo.Person
set FavoriteColor = 'Green'
where Name = 'Bob'
2. 同樣的問題,除了現在刪除,我應該檢查它是否存在嗎?

if exists ( select FavoriteColor from dbo.Person where Name = ‘Bob’ and FavoriteColor = ‘Green’ ) delete dbo.Person where Name = ‘Bob’ and FavoriteColor = ‘Green’



我們使用 SQL Server 2016。

通常,這種模式效率更高,並且不太可能導致死鎖或其他並發問題:

UPDATE dbo.Person
 SET FavoriteColor = 'Green'
 WHERE Name = 'Bob'
 AND COALESCE(FavoriteColor, '') <> 'Green';

DELETE dbo.Person
 WHERE Name = 'Bob' 
 AND FavoriteColor = 'Green';

…僅僅是因為您只需檢查該行一次。你也可以這樣寫UPDATE

UPDATE dbo.Person
 SET FavoriteColor = 'Green'
 WHERE Name = 'Bob'
 AND (FavoriteColor IS NULL OR FavoriteColor <> 'Green');

…在某些情況下可能對索引更友好。

直到實際更新要修改的行之前,才會使用寫操作的排他鎖。當 SQL Server搜尋要更新的行時,它使用更新鎖,這與並發讀取不衝突。如果 SQL Server 確定正在檢查的行不符合更新條件,則會立即釋放更新鎖。

我能想到使用該if exists方法的唯一原因是UPDATE/DELETE表中是否存在您希望避免被觸發的觸發器,特別是如果您有INSTEAD OF觸發器可以在實際嘗試任何更新或刪除之前採取一些操作。

通常最好編寫 DML,以便只影響需要更改的行。

引用自:https://dba.stackexchange.com/questions/187327