Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

C# &SQL Server – beste Möglichkeit, mehrere Zeilen auf einmal mit einer gespeicherten Prozedur zu löschen

Sie könnten Tabellenwertparameter verwenden, um dies zu übergeben. Die Anwendungsschicht würde in etwa so aussehen:

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

Dieser Ansatz hat gegenüber dem Erstellen von Zeichenfolgen eine Reihe von Vorteilen

  • Sie vermeiden das Erstellen von Abfragen in der Anwendungsschicht, wodurch eine Trennung von Bedenken entsteht
  • Sie können Ausführungspläne einfacher testen und Abfragen optimieren
  • Sie sind weniger anfällig für SQL-Injection-Angriffe, da Ihr gegebener Ansatz nicht in der Lage wäre, eine parametrisierte Abfrage zum Erstellen der IN-Klausel zu verwenden
  • Der Code ist besser lesbar und anschaulicher
  • Sie bauen am Ende keine übermäßig langen Strings auf

Leistung

Es gibt einige Überlegungen zur Leistung von TVPs bei großen Datensätzen.

Da TVPs Variablen sind, erstellen sie keine Statistiken. Das bedeutet, dass der Abfrageoptimierer den Ausführungsplan manchmal verfälschen kann. Wenn dies passiert, gibt es ein paar Optionen:

  • set OPTION (RECOMPILE) auf alle TVP-Anweisungen, bei denen die Indizierung ein Problem darstellt
  • Schreiben Sie das TVP in eine lokale Temp und richten Sie dort die Indizierung ein

Hier ist ein großartiger Artikel über TVPs mit einem guten Abschnitt über Leistungsüberlegungen und was wann zu erwarten ist.

Wenn Sie sich also Sorgen machen, Grenzwerte für Zeichenfolgenparameter zu erreichen, könnten die Tabellenwertparameter der richtige Weg sein. Aber am Ende ist es schwer zu sagen, ohne mehr über den Datensatz zu wissen, mit dem Sie arbeiten.