sql >> データベース >  >> RDS >> Sqlserver

C# &SQL Server - ストアド プロシージャを使用して一度に複数の行を削除する最良の方法

    テーブル値パラメーターを使用してこれを処理できます。アプリケーション層は

    のようになります

    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
    

    このアプローチには、文字列を構築するよりも多くの利点があります

    • アプリケーション レイヤーでクエリを作成することを避け、関心の分離を作成します
    • より簡単に実行計画をテストし、クエリを最適化できます
    • 指定されたアプローチではパラメータ化されたクエリを使用して IN 句を作成できないため、SQL インジェクション攻撃に対する脆弱性が低くなります
    • コードがより読みやすく、わかりやすくなっています
    • 過度に長い文字列を作成することはありません

    パフォーマンス

    大規模なデータセットでの TVP のパフォーマンスについて、いくつかの考慮事項があります。

    TVP は変数であるため、統計を編集しません。これは、クエリ オプティマイザが実行計画を時々ごまかす可能性があることを意味します。これが発生した場合、いくつかのオプションがあります:

    • set OPTION (RECOMPILE) インデックス作成が問題となる TVP ステートメント
    • TVP をローカル一時ファイルに書き込み、そこにインデックスを設定します

    TVP に関する素晴らしい記事はこちら パフォーマンスに関する考慮事項と、いつ何を期待するかについての適切なセクションがあります。

    そのため、文字列パラメーターの制限に達することが心配な場合は、テーブル値パラメーターを使用することをお勧めします。しかし、最終的には、使用しているデータ セットについて詳しく知らなければ、何とも言えません。



    1. この Sql Server 階層を継承された包括的なリストに簡単にフラット化するにはどうすればよいですか?

    2. JDBCエラーが発生しましたが、MySQLワークベンチでクエリを実行してもエラーは発生しません

    3. SQLite VACUUM

    4. グループ化して列を追加