2013-06-23 24 views
6

我無法弄清楚這是否可以接受的操作。我需要從SQL Server 2008數據庫中選擇記錄,然後將它們從ASP.NET代碼中作爲單個事務刪除。請注意,.NET代碼必須能夠檢索首先選擇的數據。我可以先在一個t-SQL事務中選擇並刪除記錄嗎?

東西這樣:

SELECT * FROM [tbl] WHERE [id] > 6; 
DELETE FROM [tbl] WHERE [id] > 6 

trying it與SQL小提琴但後來如果我這樣做:

SELECT * FROM [tbl] 

我得到的全表好像沒有刪除。

編輯按照要求如下下面是完整的.NET代碼檢索記錄:

string strSQLStatement = "SELECT * FROM [tbl] WHERE [id] > 6;" + 
    "DELETE FROM [tbl] WHERE [id] > 6"; 

using (SqlCommand cmd = new SqlCommand(strSQLStatement, connectionString)) 
{ 
    using (SqlDataReader rdr = cmd.ExecuteReader()) 
    { 
     while(rdr.Read()) 
     { 
      //Read values 
      val0 = rdr.GetInt32(0); 
      val3 = rdr.GetInt32(3); 
      //etc. 
     } 
    } 
} 
+1

當然可以。但請告訴我們你正在使用的代碼。 –

+0

@PreetSangha:你的意思是.NET代碼?還是SQL?如果你的意思是後者,那就好像我上面展示的那樣。 – c00000fd

+2

.Net代碼在這裏更重要 – TGH

回答

20

這將做選擇並刪除simultanious:

delete from [tbl] output deleted.* WHERE [id] > 6 
+0

哦,非常好,很簡單!我相信這種方法避免了完全處理明確的交易。 – user2246674

+0

非常優雅。謝謝! – c00000fd

+0

解決了我的問題:) –

1

是可能的選擇,並且只要在同一個事務中刪除的兩個操作在同一事務中登記。

看看這個帖子 Transactions in .net

+0

你的意思是我必須在最後放置'BEGIN TRANSACTION'和'COMMIT'嗎? – c00000fd

+0

是的,但我會建議您通過.Net管理交易而不是數據庫。這樣可以更好地控制代碼 – TGH

+0

請您詳細說明「通過.Net管理交易」嗎? – c00000fd

1

的「最簡單」的方式來實現與兼容的供應商交易(SQL Server的偉大工程!)是使用TransactionScope。只要確保在之前創建了範圍,就可以打開連接,以便正確註冊所有內容。

SelectStuffDeleteStuff方法的內容並不重要 - 只需使用相同的連接,不要手動混淆連接或事務,並執行SQL操作,但是最好。

// Notes 
// - Create scope OUTSIDE/BEFORE connection for automatic enlisting 
// - Create only ONE connection inside to avoid DTC and "advanced behavior" 
using (var ts = new TransactionScope()) 
using (var conn = CreateConnection()) { 
    // Make sure stuff selected is MATERIALIZED: 
    // If a LAZY type (Enumerable/Queryable) is returned and used later it 
    // may cause access to the connection outside of when it is valid! 
    // Use "ToList" as required to force materialization of such sequences. 
    var selectedStuff = SelectStuff(conn); 

    DeleteStuff(conn); 

    // Commit 
    ts.Complete(); 

    // Know stuff is deleted here, and access selected stuff. 
    return selectedStuff; 
} 
+0

謝謝。這是一個有趣的方法。我不知道那個階級是存在的。我需要嘗試一下。 – c00000fd

+0

另外請確保您獲得交易權利的隔離。 –

+0

@PreetSangha良好的調用 - 我通常默認(如同TransactionScope)可序列化以進行更新操作。是的,這很懶惰,正確的隔離級別是一個完全不同的主題,但它會「正常工作」或「無法工作」。 – user2246674

0

從多個SQL語句返回值是最後聲明來看,在這種情況下是DELETE的結果。沒有從DELETE返回的行,因此val0val3沒有任何可讀的內容。

有兩個解決方案,我能想到的在這裏:

  1. 更改您的代碼,明確啓動事務,執行SELECT,讀出的值,然後發出DELETE,或

  2. SELECT轉換爲#temp表,執行DELETE,然後從#temp表中執行SELECT表,執行所需要的與行有關的操作,然後執行DROP th。

+0

謝謝。我之所以這麼做的原因是因爲我需要這個操作被'原子地'執行。 – c00000fd

+0

由於腳本語句的結果是執行最後一條語句的結果,因此無法自動執行AFAIK。第二種解決方案可能是最接近你將得到的,因爲它會快速刪除行(阻止其他連接讀取它們)並保留它們,以便仍然可以訪問它們。 –

相關問題