Rob*_*015 3 c# performance sql-server-2012 sql-server-2014
我知道那里所以这里的许多相同经历的问题,我的问题是,如果我想删除说1K左右行相当少,给出List<int>的RecordID,我会避免使用DataTable,并发送翻译成语句列表:
string ParmRecordsToDelete_CsvWhereIN = "("
for(int CurIdx=0; CurIdx < RecIdsToDelete.Count; CurIdx++)
{
ParmRecordsToDelete_CsvWhereIN += RecIdsToDelete[CurIdx] + ", ";
//this method to create passed parameter
//logic to remove on last Coma on last Index..
//or use stringJoin and somehow remove the last coma
}
ParRecordsToDelete_CsvWhereIN +=")";
Run Code Online (Sandbox Code Playgroud)
这将创建像"('1','2','3'......)"
然后创建一个SqlCommand调用存储过程:
Delete * From @TblName WHERE @ColName IN @RecordsToDeleteCsvWhereIN
Run Code Online (Sandbox Code Playgroud)
这是一种有效的方法吗?单个参数的长度是否有限制?我猜这是N/VARCHAR(MAX)长度.
我想如果它不是一个有点hackish解决方案它不会受到长度的限制......
什么是最好的快速解决方案,还是我在正确的轨道上?
您可以使用表值参数来处理此问题.应用程序层看起来像
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();
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
与构建字符串相比,这种方法有许多优点
性能
有关TVP在大型数据集上的性能的一些考虑因素.
因为TVP是变量,所以它们不编译统计数据.这意味着查询优化器有时可以捏造执行计划.如果发生这种情况,有两种选择:
OPTION (RECOMPILE)任何TVP语句,其中索引是一个问题这是关于TVP的一篇很棒的文章,其中有关于性能考虑的一个很好的部分,以及什么时候可以期待.
因此,如果您担心对字符串参数进行限制,那么表值参数可能是最佳选择.但最终,如果不了解您正在使用的数据集,很难说.