Insertar datos en la tabla SQL con clave primaria. Para los duplicados - ¿Permitir insertar error o Seleccionar primero?

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

  •  03-07-2019
  •  | 
  •  

Pregunta

Dada una tabla como:

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

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

Y dado que queremos una lista única de 'datos de prueba' cuando hayamos terminado de recopilar elementos para agregarlos de una lista de datos externos con duplicados conocidos ... Al realizar un procedimiento de inserción almacenada, el procedimiento debe escribirse para probar ¿Existencia o debería simplemente permitir el error? ¿Cuál es la práctica más común? Siempre he realizado la prueba de existencia, pero estuve debatiendo esta última noche ...

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
¿

o simplemente captura / ignora los errores de violación de PK al ejecutar este?

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

Solución

Siempre lo hago en una declaración:

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

Otros consejos

Su cheque para errores (es decir, " SI NO EXISTE ... ") puede o no funcionar, porque existe una condición potencial de carrera (si otra transacción inserta el registro después de su declaración IF NOT EXISTS pero antes de su declaración INSERT) ).

Por lo tanto, si verifica antes o no, debe codificar su declaración INSERT como si pudiera fallar.

Si desea comprobar también también (no, en su lugar) depende de usted y de su interfaz de usuario.

Creo que la mayoría de los programadores sugerirían evitar la excepción. No estoy seguro desde un punto de vista de rendimiento en T-SQL, pero en .NET, por ejemplo, creo que una excepción lanzada es más costosa que una declaración if / else adicional.

Mi preocupación con el primer ejemplo que dio es que no está devolviendo un error al usuario. Se puede arreglar para hacerlo, pero no lo usaría a menos que estuviera devolviendo un error.

Si tu preocupación entre las dos posibilidades es el rendimiento en tablas grandes, te sugiero que las pruebes y veas si una es significativamente más rápida que la otra. Si la selección if es particularmente complicada y la inserción tendrá que suceder por mucho la mayor parte del tiempo, es posible que simplemente dejarlo fallar sea más rápido la mayor parte del tiempo. Si, por otro lado, la posibilidad de una entrada incorrecta es alta y si es relativamente sencilla como se muestra aquí, entonces el otro proceso podría ser mejor. Pero solo las pruebas reales en su estructura de datos y datos reales y con sus consultas reales pueden decirle cuál es el mejor para el rendimiento, ya que puede ser diferente en las situaciones de diferenciación.

Creo que depende de la naturaleza del procedimiento almacenado. Básicamente, debe manejar los errores si tiene algo que ver con ellos (o para encapsularlos para los clientes del procedimiento) y dejarlos propagarse si no tiene nada que ver con ellos y no puede hacerlo más amigable para otros. Capas de la aplicación.

Si el procedimiento almacenado está diseñado para insertar datos sin procesar, creo que debería dejar que la aplicación maneje los posibles errores. Si el procedimiento almacenado está diseñado como una capa de abstracción (y hace una tarea específica en lugar de ejecutar una declaración específica) y puede manejar el error y hacer algo con él o puede reportarlo a la aplicación de manera elegante (por ejemplo, códigos de error bien definidos), debería hacerlo. De lo contrario, debería estar en la aplicación para asegurarse de que no está insertando datos duplicados, no de la base de datos (la base de datos ya lo ha aplicado con claves primarias).

Para que sea fácil de usar, a menudo es una buena práctica realizar el SELECCIONAR, y si el registro ya existe, ofrezca al usuario la oportunidad de verlo y / o editarlo.

Por ejemplo, si un usuario está agregando un nuevo registro de Cliente, es posible que desee revisar la información que ya se ha mostrado para ese Cliente. Es posible que tengan información adicional para agregar al registro, como un número de teléfono.

En este tipo de escenario, negarse a agregar el registro es menos útil que ofrecer la posibilidad de ver el duplicado existente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top