Inserir dados em tabela SQL com chave primária. Para crédulos - permitir inserção de erro ou Selecione primeiro?

StackOverflow https://stackoverflow.com/questions/411575

  •  03-07-2019
  •  | 
  •  

Pergunta

Dada uma tabela, tais como:

CREATE TABLE dbo.MyTestData (testdata varchar(50) NOT NULL) 

ALTER TABLE dbo.MyTestData WITH NOCHECK ADD CONSTRAINT [PK_MyTestData] PRIMARY KEY  CLUSTERED (testdata) 

E dado que queremos uma lista única de 'testdata' quando estamos itens recolhimento feito para ser adicionados a partir de uma lista de dados externos com duplicatas conhecidas ... Ao realizar um procedimento de inserção armazenado deve o processo ser escrito para testar existência ou deve apenas permitir o erro? Qual é a prática mais comum? Eu sempre realizaram o teste para a existência, mas foi debater esta última noite ...

CREATE PROCEDURE dbo.dmsInsertTestData @ptestdata VarChar(50)
AS
  SET NOCOUNT ON

  IF NOT EXISTS(SELECT testdata FROM dbo.MyTestData WHERE testdata=@ptestdata)
  BEGIN
    INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
  END

RETURN 0

ou apenas captura / ignorar erros violação PK ao executar este?

CREATE PROCEDURE dbo.dmsInsertTestData @ptestdata VarChar(50)
AS
  SET NOCOUNT ON
  INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
RETURN 0
Foi útil?

Solução

Eu sempre fazê-lo em uma declaração:

INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
WHERE NOT EXISTS(SELECT 1 FROM dbo.MyTestData WHERE testdata=@ptestdata)

Outras dicas

Seu cheque de erros (ou seja, "SE NÃO EXISTE ...") pode ou não pode trabalhar, porque há uma condição de corrida potencial (se outra transação insere o registro após o seu SE NÃO EXISTE declaração, mas antes de sua declaração INSERT).

Portanto, se ou não você verifique antes, você deve codificar sua instrução INSERT como se pode falhar.

Se você quiser verificar assim (não, em vez disso) é até você e até a interface do usuário.

Eu acho que a maioria dos programadores iria sugerir evitando a exceção. Eu não tenho certeza do ponto de vista do desempenho no T-SQL, mas em .NET, por exemplo, eu acredito que uma exceção lançada é mais caro do que um if / else adicional.

A minha preocupação com o primeiro exemplo que você deu é que ele não está retornando um erro para o usuário. Ele pode ser fixado a fazê-lo, mas eu não iria utilizá-lo a menos que ele estava retornando um erro.

Se a sua preocupação entre os dois possibilties é o desempenho em tabelas grandes, eu sugiro que você testar os dois e ver se um é significativamente mais rápido do que o outro. Se o caso de seleção é particularmente complicada e a inserção terá de acontecer, de longe, a maior parte do tempo, é possível que simplesmente deixá-lo falhar seria mais rápido na maioria das vezes. Se onthe outro lado, a possibilidade de uma entrada ruim é alta eo caso é relativamente simples, como mostrado aqui, então o outro processo pode ser um melhor. Mas só verdadeiro teste em sua estrutura de dados real e de dados e com suas consultas reais podem dizer-lhe que é o melhor um para o desempenho, uma vez que pode ser differnt em situaltions deiffernt.

Eu acredito que depende da natureza do procedimento armazenado. Basicamente, você deve lidar com erros se você tem algo a ver com eles (ou para encapsular-los para os clientes do procedimento) e deixá-los propagação se você não tem nada a ver com eles e não pode torná-lo mais amigável para outra camadas da aplicação.

Se o procedimento armazenado é projetado para inserir dados em bruto, eu acho que deveria deixar a aplicação para lidar com os possíveis erros. Se o procedimento armazenado é concebido como uma camada de abstração (e faz um específico tarefa ao invés de executar um específico declaração ) e pode manipular o erro e fazer algo com ele ou pode denunciá-lo de uma forma graciosa (por exemplo, códigos de erro bem definidas) para o aplicativo, ele deve fazê-lo. Caso contrário, ele deve ser até a aplicação para se certificar de que não está inserindo dados duplicados, e não o banco de dados (o banco de dados já aplicadas isso com chaves primárias).

Para ser user-friendly, muitas vezes é uma boa prática para realizar o SELECT, e se o registro já existe, oferecer ao usuário a oportunidade de ver e / ou editá-lo.

Por exemplo, se um usuário está adicionando um novo registro do cliente, eles podem querer rever a informação que já foi apresentada para que o Cliente. Eles podem ter informações adicionais para adicionar ao registro, como um número de telefone.

Neste tipo de cenário, recusando-se a adicionar o registro é menos útil do que oferecer a capacidade de visualizar o duplicado existente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top