2013-06-23 7 views
6

Nie mogę stwierdzić, czy jest to operacja akceptowalna. Muszę wybrać rekordy z bazy danych SQL Server 2008, a następnie je usunąć, wszystkie jako pojedynczą transakcję z kodu ASP.NET. Zauważ, że kod .NET musi być w stanie pobrać dane, które zostały wybrane jako pierwsze.Czy mogę najpierw WYBRAĆ, a następnie USUWAĆ rekordy w jednej transakcji t-SQL?

Coś takiego jak:

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

jestem trying it z SQL Fiddle ale jeśli robię:

SELECT * FROM [tbl] 

uzyskać pełną tabelę tak, jakby nic nie zostało usunięte.

EDIT Zgodnie z wnioskiem poniżej oto pełny kod .NET aby pobrać rekordy:

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

Tak można. Pokaż nam kod, którego używasz. –

+0

@PreetSangha: Masz na myśli kod .NET? Lub SQL? Jeśli masz na myśli to ostatnie, to jest tak, jak pokazałem powyżej. – c00000fd

+2

kod .Net jest ważniejszy tutaj – TGH

Odpowiedz

20

to zrobi select i usuwać simultanious:

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

Ooh, bardzo ładne i proste! Uważam, że takie podejście pozwala uniknąć całkowicie zajmować się jawnymi transakcjami. – user2246674

+0

Bardzo elegancki. Dziękuję Ci! – c00000fd

+0

rozwiązał mój problem :) –

1

Jest możliwe, aby zaznaczyć i usunąć w tej samej transakcji, o ile obie operacje są zaciągnął w tej samej transakcji .

Spójrz na tym stanowisku Transactions in .net

+0

Czy masz na myśli, że muszę na końcu napisać "BEGIN TRANSACTION", a potem "COMMIT"? – c00000fd

+0

Tak, ale polecam zarządzanie transakcjami przez .Net, a nie DB. To daje lepszą kontrolę z kodu – TGH

+0

Czy możesz rozwinąć ten "zarządzanie transakcjami przez .Net"? – c00000fd

1

W „najłatwiejszy” sposobem osiągnięcia transakcji z kompatybilnym operatora (SQL Server działa świetnie!) Jest użycie TransactionScope. Po prostu upewnij się, że zakres został utworzony przed połączenie zostanie otwarte, aby wszystko zostało poprawnie zarejestrowane.

Treść metod nie ma większego znaczenia - wystarczy użyć tego samego połączenia, nie ręcznie komunikować się z połączeniem lub z transakcjami i wykonywać operacje SQL, jednak jest najlepsza.

// 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

Dzięki. To interesujące podejście. Nie wiedziałem, że ta klasa istnieje. Muszę to wypróbować. – c00000fd

+0

Upewnij się także, czy poprawnie wyceniono transakcję. –

+0

@PreetSangha Good call - Domyślnie (tak jak TransactionScope) do serializacji dla operacji aktualizacji. Tak, jest leniwy, a właściwy poziom izolacji to zupełnie inny temat, ale albo "zadziała poprawnie", albo "nie zadziała". – user2246674

0

Wartość zwracana z wielu SQL jest wynikiem ostatniego uruchomienia wyciągu, który w tym przypadku jest DELETE. Nie ma wierszy zwróconych od DELETE, więc nie ma nic do czytania dla val0 i.

Istnieją dwa rozwiązania można myślę tutaj:

  1. zmienić swój kod, aby wyraźnie rozpocząć transakcję, należy wykonać SELECT, odczytać wartości, a następnie wydać DELETE lub

  2. SELECT do tabeli , wykonaj DELETE, a następnie SELECT z tabeli #temp, zrób co trzeba z wierszami, a następnie DROP th.

+0

Dzięki. Powodem, dla którego robiłem to tak, jak pokazałem to powyżej, jest to, że potrzebuję tej operacji do wykonania "atomowo". – c00000fd

+0

Nie ma sposobu, aby zrobić to atomicznie, AFAIK, ponieważ wynik instrukcji skryptowych jest wynikiem ostatniej wykonanej instrukcji. Drugie rozwiązanie jest prawdopodobnie najbliższe, ponieważ szybko usunie je (uniemożliwiając odczytanie innych połączeń) i zachowa je, aby można było uzyskać do nich dostęp. –

Powiązane problemy