sql >> Databáze >  >> RDS >> Sqlserver

Jak implementovat podmíněnou uloženou proceduru Upsert?

Dal jsem dohromady následující scénář, abych dokázal tento trik, který jsem používal v minulých letech. Pokud jej používáte, budete jej muset upravit tak, aby vyhovoval vašim účelům. Následují komentáře:

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

Trik je v tom, že můžete nastavit hodnoty v lokálních proměnných v příkazu Update. Výše se hodnota "flag" nastaví pouze v případě, že aktualizace funguje (to znamená, že jsou splněna kritéria aktualizace); jinak se nezmění (zde ponecháno na null), můžete to zkontrolovat a podle toho zpracovat.

Pokud jde o transakci a její serializaci, rád bych se dozvěděl více o tom, co musí být v transakci zapouzdřeno, než navrhnu, jak postupovat.

-- Dodatek, pokračování z druhého komentáře níže -----------

Nápady pana Saffrona jsou důkladným a spolehlivým způsobem implementace této rutiny, protože vaše primární klíče jsou definovány mimo a předány do databáze (tj. nepoužíváte sloupce identity – podle mě dobře, často jsou nadměrně používány).

Provedl jsem další testování (přidal omezení primárního klíče do sloupce ContentId, zabalil UPDATE a INSERT do transakce, přidal serializovatelnou nápovědu k aktualizaci) a ano, to by mělo dělat vše, co chcete. Neúspěšná aktualizace udeří do této části indexu zámek rozsahu, který zablokuje všechny současné pokusy o vložení této nové hodnoty do sloupce. Samozřejmě, pokud je současně odesláno N požadavků, „první“ vytvoří řádek a ten bude okamžitě aktualizován druhým, třetím atd. – pokud někde na řádku nenastavíte „zámek“. Dobrý trik!

(Všimněte si, že bez indexu ve sloupci klíče byste zamkli celou tabulku. Zámek rozsahu také může zamknout řádky na „kterékoli straně“ nové hodnoty – nebo možná nebudou, já to neudělal otestujte to. Na tom nezáleží, protože doba trvání operace by měla být [?] v jednociferných milisekundách.)



  1. NASTAVIT NÁZVY utf8 v MySQL?

  2. Funkce Escape pro regulární výraz nebo vzory LIKE

  3. dotaz na databázi mysql zevnitř třídy

  4. Nové funkce SQL Server 2019