Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

АКТУАЛИЗИРАНЕ, ако съществува друго INSERT в SQL Server 2008

Много хора ще ви предложат да използвате MERGE , но ви предупреждавам срещу това. По подразбиране той не ви защитава от паралелност и условия на състезание повече от множество изявления, но въвежда други опасности:

  • Внимавайте с изявлението MERGE на SQL Server
  • Какво да избягвате, ако искате да използвате MERGE
  • SQL Server UPSERT шаблони и антимодели

Дори с наличен този "по-прост" синтаксис, аз все още предпочитам този подход (обработката на грешки е пропусната за краткост):

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;

Повече информация за този UPSERT подход тук:

  • Моля, спрете да използвате този анти-модел на UPSERT

Много хора ще предложат този начин:

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;

Но всичко това постига гарантира, че може да се наложи да прочетете таблицата два пъти, за да намерите редовете, които трябва да бъдат актуализирани. В първата извадка ще трябва да намерите редовете само веднъж. (И в двата случая, ако не бъдат намерени редове от първоначалното четене, се получава вмъкване.)

Други ще предложат този начин:

BEGIN TRY
  INSERT ...
END TRY
BEGIN CATCH
  IF ERROR_NUMBER() = 2627
    UPDATE ...
END CATCH

Това обаче е проблематично, ако не по друга причина, освен да позволите на SQL Server да улавя изключения, които бихте могли да предотвратите на първо място, е много по-скъпо, освен в редкия сценарий, при който почти всяко вмъкване се проваля. Доказвам толкова много тук:

  • Проверка за потенциални нарушения на ограниченията, преди да влезете в TRY/CATCH
  • Влияние върху производителността на различни техники за обработка на грешки

Не сте сигурни какво мислите, че печелите, като имате едно изявление; Не мисля, че печелиш нищо. MERGE е едно изявление, но така или иначе трябва наистина да изпълнява множество операции - въпреки че ви кара да мислите, че не го прави.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Вземете списък с пощенски акаунти в базата данни в SQL Server (T-SQL)

  2. Най-бързият начин за извършване на вложени групови вмъквания с използване на scope_identity()?

  3. Изрична стойност за колоната за идентичност в таблицата може да бъде посочена само когато се използва списък с колони и IDENTITY_INSERT е ON SQL Server

  4. Как да съкратите всички таблици в база данни с помощта на TSQL?

  5. PIVOT заявка към различни записи