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

C# e SQL Server - melhor maneira de excluir várias linhas de uma só vez usando um procedimento armazenado


Você pode usar parâmetros com valor de tabela para entregar isso. A camada de aplicação seria algo como

C#
var tvp = new DataTable();
tvp.Columns.Add("Id", typeof(int));

foreach(var id in RecIdsToDelete)
    tvp.Rows.Add(new {id});

var connection = new SqlConnection("your connection string");

var delete = new SqlCommand("your stored procedure name", connection)
{
  CommandType = CommandType.StoredProcedure
};

delete
  .Parameters
  .AddWithValue("@ids", tvp)
  .SqlDbType = SqlDbType.Structured;

delete.ExecuteNonQuery();

SQL
IF NOT EXISTS(SELECT * FROM sys.table_types WHERE name = 'IDList')
BEGIN
    CREATE TYPE IDList AS TABLE(ID INTEGER)
END


CREATE PROCEDURE School.GroupStudentDelete
(                                         
        @IDS IDLIST READONLY      
)                                         
AS

SET NOCOUNT ON;

BEGIN TRY
        BEGIN TRANSACTION

        DECLARE @Results TABLE(id INTEGER)

        DELETE 
        FROM TblName 
        WHERE Id IN (SELECT ID FROM @IDS)        

        COMMIT TRANSACTION
END TRY
BEGIN CATCH
        PRINT ERROR_MESSAGE();

        ROLLBACK TRANSACTION
        THROW; -- Rethrow exception
END CATCH
GO

Há uma série de vantagens para esta abordagem sobre a construção de strings
  • Você evita criar consultas na camada do aplicativo, criando uma separação de preocupações
  • Você pode testar planos de execução com mais facilidade e otimizar consultas
  • Você está menos vulnerável a ataques de injeção de SQL, já que sua abordagem dada não seria capaz de usar uma consulta parametrizada para construir a cláusula IN
  • O código é mais legível e ilustrativo
  • Você não acaba criando strings excessivamente longas

Desempenho

Existem algumas considerações sobre o desempenho de TVPs em grandes conjuntos de dados.

Como os TVPs são variáveis, eles não compilam estatísticas. Isso significa que o otimizador de consulta pode enganar o plano de execução às vezes. Se isso acontecer, há algumas opções:
  • definir OPTION (RECOMPILE) em quaisquer declarações de TVP em que a indexação seja um problema
  • grave o TVP em um local temporário e configure a indexação lá

Aqui está um ótimo artigo sobre TVPs com uma boa seção sobre considerações de desempenho e o que esperar quando.

Portanto, se você está preocupado em atingir os limites dos parâmetros de string, os parâmetros com valor de tabela podem ser o caminho a seguir. Mas, no final, é difícil dizer sem saber mais sobre o conjunto de dados com o qual você está trabalhando.