Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

UPDATE se existir mais INSERT no SQL Server 2008


Muitas pessoas irão sugerir que você use MERGE , mas eu o alerto contra isso. Por padrão, ele não protege você de condições de concorrência e corrida mais do que várias instruções, mas apresenta outros perigos:
  • Tenha cuidado com a instrução MERGE do SQL Server
  • O que evitar se você quiser usar MERGE
  • Padrões e antipadrões UPSERT do SQL Server

Mesmo com essa sintaxe "mais simples" disponível, ainda prefiro essa abordagem (tratamento de erros omitido por brevidade):
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;

Mais informações sobre este UPSERT abordagem aqui:
  • Pare de usar este antipadrão UPSERT

Muita gente vai sugerir desta forma:
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;

Mas tudo isso garante que você precise ler a tabela duas vezes para localizar as linhas a serem atualizadas. Na primeira amostra, você só precisará localizar a(s) linha(s) uma vez. (Em ambos os casos, se nenhuma linha for encontrada na leitura inicial, ocorrerá uma inserção.)

Outros irão sugerir desta forma:
BEGIN TRY
  INSERT ...
END TRY
BEGIN CATCH
  IF ERROR_NUMBER() = 2627
    UPDATE ...
END CATCH

No entanto, isso é problemático se por nenhum outro motivo além de permitir que o SQL Server capture exceções que você poderia ter evitado em primeiro lugar for muito mais caro, exceto no raro cenário em que quase todas as inserções falham. Provo isso aqui:
  • Verificando possíveis violações de restrições antes de inserir TRY/CATCH
  • Impacto no desempenho de diferentes técnicas de tratamento de erros

Não tenho certeza do que você acha que ganha por ter uma única declaração; Acho que você não ganha nada. MERGE é uma única instrução, mas ainda precisa executar várias operações de qualquer maneira - mesmo que faça você pensar que não.