Me gustaría poder predecir si un DELETE se encontrará con una violación de restricción, sin realizar realmente la eliminación.
¿Cuáles son mis opciones para hacer esto? ¿Hay una manera simple de hacer una "ejecución en seco" de un DELETE?
Me gustaría poder predecir si un DELETE se encontrará con una violación de restricción, sin realizar realmente la eliminación.
¿Cuáles son mis opciones para hacer esto? ¿Hay una manera simple de hacer una "ejecución en seco" de un DELETE?
Respuestas:
Si su objetivo es procesar todas las eliminaciones solo si todas tienen éxito, ¿por qué no usar TRY / CATCH?
BEGIN TRANSACTION;
BEGIN TRY
DELETE #1;
DELETE #2;
DELETE #3;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH
Si el objetivo es permitir que todas las eliminaciones exitosas tengan éxito incluso si una o más fallan, entonces puede usar TRY / CATCH individual, por ejemplo
BEGIN TRY
DELETE #1;
END TRY
BEGIN CATCH
PRINT 1;
END CATCH
BEGIN TRY
DELETE #2;
END TRY
BEGIN CATCH
PRINT 1;
END CATCH
Una opción es comenzar una transacción, ejecutar su eliminación y luego siempre revertir:
begin tran
delete Table1 where col1 = 1
-- Test whether it is there
select * from Table1 where col1 = 1
rollback tran
-- Confirm that it is still there
select * from Table1 where col1 = 1
Me gustaría mejorar la solución provista por Aaron Bertrand con algún código, en caso de que desee intentar agregar algún elemento de una tabla, administrar las excepciones para ignorar fallas o también detener el proceso después de los errores.
Éste seleccionará los registros de la tabla y luego intenta eliminarlos sin excepciones:
DECLARE @MaxErrors INT
SET @MaxErrors = 5; // Setting 0 will stop process after the first error!
SELECT
[Id]
, ROW_NUMBER() OVER (ORDER BY Id ASC) AS [Index]
INTO #DeletingItems
FROM myTable
DECLARE @Current INT, @Max INT, @Id INT, @TotErrors INT
SELECT
@Current = 1
, @TotErrors = 0
, @Max = MAX([Index])
FROM #DeletingTable
WHILE @Current <= @Max
BEGIN
SELECT
@Id = [Id]
FROM #DeletingItems
WHERE
[Index] = @Index;
BEGIN TRANSACTION;
BEGIN TRY
DELETE FROM myTable WHERE [Id] = @Id;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
SET @TotErrors = @TotErrors + 1;
IF @TotErrors > @MaxErrors
BREAK;
END CATCH
SET @Current = @Current + 1;
END