Molte persone ti suggeriranno di utilizzare MERGE
, ma ti avverto di non farlo. Per impostazione predefinita, non ti protegge dalla concorrenza e dalle condizioni di gara non più di più dichiarazioni, ma introduce altri pericoli:
- Utilizzare Attenzione con l'istruzione MERGE di SQL Server
- Cosa evitare se si desidera utilizzare MERGE
- Pattern e antipattern UPSERT di SQL Server
Anche con questa sintassi "più semplice" disponibile, preferisco comunque questo approccio (gestione degli errori omessa per brevità):
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE dbo.table SET ... WHERE PK = @PK;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.table(PK, ...) SELECT @PK, ...;
END
COMMIT TRANSACTION;
Maggiori informazioni su questo UPSERT
avvicinati qui:
- Per favore, smetti di usare questo anti-modello UPSERT
Molte persone suggeriranno in questo modo:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
IF EXISTS (SELECT 1 FROM dbo.table WHERE PK = @PK)
BEGIN
UPDATE ...
END
ELSE
BEGIN
INSERT ...
END
COMMIT TRANSACTION;
Ma tutto ciò garantisce che potrebbe essere necessario leggere la tabella due volte per individuare le righe da aggiornare. Nel primo esempio, dovrai individuare le righe una sola volta. (In entrambi i casi, se non vengono trovate righe dalla lettura iniziale, si verifica un inserimento.)
Altri suggeriranno in questo modo:
BEGIN TRY
INSERT ...
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 2627
UPDATE ...
END CATCH
Tuttavia, questo è problematico se non altro per il fatto che consentire a SQL Server di rilevare le eccezioni che avresti potuto evitare in primo luogo è molto più costoso, tranne nel raro scenario in cui quasi tutti gli inserimenti non riescono. Lo dimostro qui:
- Verifica di potenziali violazioni dei vincoli prima di accedere a TRY/CATCH
- Impatto sulle prestazioni delle diverse tecniche di gestione degli errori
Non sono sicuro di cosa pensi di guadagnare avendo una singola affermazione; Non credo che guadagni nulla. MERGE
è una singola istruzione ma deve comunque eseguire davvero più operazioni, anche se ti fa pensare che non lo faccia.