2012-10-10 49 views
1
   if exists (select 1 from schema.TableName (nolock) where Id = @id) 
       update schema.TableName set DocumentXML = @documentXml, [email protected], Incomplete = @incomplete where Id = @id 
       else 
       insert into schema.TableName 
       select @id, @templateId, @clientVisitGuid, @clientGuid, @chartGuid, @scmDocumentGuid, @clientDocGuid, @incomplete, getdate(), @createdByGuid, @documentXml 

我有一個運行上面查詢的C#程序。我遇到了行插入兩次的情況。我認爲這個問題是這個查詢。這個想法是,查詢可以運行兩次給定相同@Id。第一次應該是插入,第二次應該是更新。同一查詢的不鎖定運行

請注意查詢有一個(no lock)。這是否意味着查詢不一定以FIFO方式運行?我相信只有我異步運行此查詢時纔會出現兩行問題。

+0

[只插入一行,如果它不在那裏]可能的重複(http://stackoverflow.com/questions/3407857/only-inserting-a-row-if-its-not-already-there) –

回答

1

如果你有兩個請求的處理在同一時間,因爲你忽略第一個表中的所有的鎖,他們都將插入。在這些情況下,我喜歡使用merge。或者刪除你的無鎖,並確保你的事務隔離級別是快照或序列化。

0

取決於事務隔離級別的查詢可以並行運行...

0

使用NOLOCK提示會導致SQL Server忽略所有鎖。這意味着一個查詢可能最終會讀取正在被更改的值,這會導致完全垃圾被返回。

但是,刪除NOLOCK提示是不夠的。您需要確保您的所有語句都在調用應用程序或過程中的事務中執行。如果你首先進行一個程序審查:How to rollback in procedures

在將事務包裝在事務中之後,還需要確保IF EXISTS語句正在對行進行更新或排它鎖以防止其他人插入在你的陳述之間有一行,所以你需要一個UPDLOCK或一個XLOCK提示。由於該行可能不存在,因此這也只能在可序列化的事務隔離級別中使用。

執行完所有這些之後,您仍然在使用此設置浪費時間。這可能會在稍後成爲性能問題。

-

長話短說:作爲JoshBerke建議,你應該使用MERGE語句在這種情況下。這可以防止您的問題,同時更快,更容易維護。但是,它需要2008或更高版本。詳情請參閱http://msdn.microsoft.com/en-us/library/bb510625.aspx