Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak zaimplementować warunkową procedurę składowaną Upsert?

Złożyłem razem następujący skrypt, aby udowodnić tę sztuczkę, której używałem w poprzednich latach. Jeśli go używasz, musisz go zmodyfikować, aby odpowiadał Twoim celom. Komentarze następują:

/*
CREATE TABLE Item
 (
   Title      varchar(255)  not null
  ,Teaser     varchar(255)  not null
  ,ContentId  varchar(30)  not null
  ,RowLocked  bit  not null
)


UPDATE item
 set RowLocked = 1
 where ContentId = 'Test01'

*/


DECLARE
  @Check varchar(30)
 ,@pContentID varchar(30)
 ,@pTitle varchar(255)
 ,@pTeaser varchar(255)

set @pContentID = 'Test01'
set @pTitle     = 'TestingTitle'
set @pTeaser    = 'TestingTeasier'

set @check = null

UPDATE dbo.Item
 set
   @Check = ContentId
  ,Title  = @pTitle
  ,Teaser = @pTeaser
 where ContentID = @pContentID
  and RowLocked = 0

print isnull(@check, '<check is null>')

IF @Check is null
    INSERT dbo.Item (ContentID, Title, Teaser, RowLocked)
     values (@pContentID, @pTitle, @pTeaser, 0)

select * from Item

Sztuczka polega na tym, że możesz ustawić wartości w zmiennych lokalnych w instrukcji Update. Powyżej wartość „flagi” jest ustawiana tylko wtedy, gdy aktualizacja działa (czyli spełnione są kryteria aktualizacji); w przeciwnym razie nie zostanie zmieniony (tutaj pozostawiony na null), możesz to sprawdzić i odpowiednio przetworzyć.

Jeśli chodzi o transakcję i umożliwienie jej serializacji, chciałbym dowiedzieć się więcej o tym, co musi być zawarte w transakcji, zanim zasugeruję, jak postępować.

-- Uzupełnienie, kontynuacja drugiego komentarza poniżej -----------

Pomysły pana Saffrona są dokładnym i solidnym sposobem realizacji tej procedury, ponieważ klucze podstawowe są definiowane na zewnątrz i przekazywane do bazy danych (tzn. nie używasz kolumn tożsamości – w porządku, są one często nadużywane).

Zrobiłem trochę więcej testów (dodałem ograniczenie klucza podstawowego do kolumny ContentId, zawinąłem UPDATE i INSERT w transakcję, dodałem podpowiedź do serializacji do aktualizacji) i tak, to powinno zrobić wszystko, co chcesz. Nieudana aktualizacja powoduje nałożenie blokady zakresu na tę część indeksu, co zablokuje wszelkie jednoczesne próby wstawienia tej nowej wartości do kolumny. Oczywiście, jeśli N żądań zostanie przesłanych jednocześnie, „pierwszy” utworzy wiersz i zostanie on natychmiast zaktualizowany przez drugi, trzeci itd. – chyba że ustawisz „kłódkę” gdzieś wzdłuż linii. Dobra sztuczka!

(Zauważ, że bez indeksu w kolumnie klucza zablokowałbyś całą tabelę. Ponadto blokada zakresu może zablokować wiersze po „po dowolnej stronie” nowej wartości — a może nie, ja tego nie zrobiłem przetestuj to. Nie powinno mieć znaczenia, ponieważ czas trwania operacji powinien [?] być w jednocyfrowych milisekundach.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak dodać atrybuty do węzłów xml w serwerze sql 2005

  2. SqlConnection SqlCommand SqlDataReader IDisposable

  3. Jak dołączyć trzecią tabelę w mojej instrukcji SQL, która zwraca LICZBA bez utraty elementów licznika 0?

  4. Jak mogę wykonać tę kwerendę w programie SQL Server Compact Edition?

  5. Najszybszy sposób na aktualizację 120 milionów rekordów