在SqlCommand中使用params删除

我使用ADO.NET从DB中删除一些数据,如下所示:

using (SqlConnection conn = new SqlConnection(_connectionString)) { try { conn.Open(); using (SqlCommand cmd = new SqlCommand("Delete from Table where ID in (@idList);", conn)) { cmd.Parameters.Add("@idList", System.Data.SqlDbType.VarChar, 100); cmd.Parameters["@idList"].Value = stratIds; cmd.CommandTimeout = 0; cmd.ExecuteNonQuery(); } } catch (Exception e) { //_logger.LogMessage(eLogLevel.ERROR, DateTime.Now, e.ToString()); } finally { conn.Close(); } } 

该代码在没有Exception的情况下执行,但数据未从DB中删除。 当我使用相同的算法插入或更新数据库时,一切正常。 有谁知道这是什么问题?

您不能在常规TSQL中执行此操作,因为服务器将@idList视为恰好包含逗号的单个值。 但是,如果使用List ,则可以使用dapper-dot-net

 connection.Execute("delete from Table where ID in @ids", new { ids=listOfIds }); 

dapper指出你的意思,并产生适当的参数化。

另一种选择是发送一个字符串并编写一个UDF来执行“拆分”操作,然后在查询中使用该UDF:

 delete from Table where ID in (select Item from dbo.Split(@ids)) 

根据Marc的Split-UDF,这是一个有效的实现:

 CREATE FUNCTION [dbo].[Split] ( @ItemList NVARCHAR(MAX), @delimiter CHAR(1) ) RETURNS @IDTable TABLE (Item VARCHAR(50)) AS BEGIN DECLARE @tempItemList NVARCHAR(MAX) SET @tempItemList = @ItemList DECLARE @i INT DECLARE @Item NVARCHAR(4000) SET @tempItemList = REPLACE (@tempItemList, ' ', '') SET @i = CHARINDEX(@delimiter, @tempItemList) WHILE (LEN(@tempItemList) > 0) BEGIN IF @i = 0 SET @Item = @tempItemList ELSE SET @Item = LEFT(@tempItemList, @i - 1) INSERT INTO @IDTable(Item) VALUES(@Item) IF @i = 0 SET @tempItemList = '' ELSE SET @tempItemList = RIGHT(@tempItemList, LEN(@tempItemList) - @i) SET @i = CHARINDEX(@delimiter, @tempItemList) END RETURN END 

这就是你怎么称呼它:

 DELETE FROM Table WHERE (ID IN (SELECT Item FROM dbo.Split(@idList, ','))); 

我想更多地讨论这个问题。 这似乎属于“ 我如何获取多行数据到sql ”的主题。 在@Kate的情况下,她正在尝试DELETE-WHERE-IN,但是这个用户案例的有用策略与UPDATE-FROM-WHERE-IN或INSERT INTO-SELECT FROM的策略非常相似。 我看到它的方式有一些基本策略。

字符串连接

这是最古老,最基本的方式。 你做一个简单的“SELECT * FROM MyTable WHERE ID IN(”+ someCSVString +“);”

  • 超级简单
  • 打开SQL注入攻击的最简单方法。
  • 你投入清理字符串的努力将更好地花在其他解决方案之一上

对象映射器

正如@MarcGravell建议你可以使用像dapper-dot-net这样的东西,就像Linq-to-sql或Entity Framework一样。 Dapper允许你进行connection.Execute("delete from MyTable where ID in @ids", new { ids=listOfIds }); 同样地,Linq会让你from t in MyTable where myIntArray.Contains( t.ID )执行类似于from t in MyTable where myIntArray.Contains( t.ID )

  • 对象映射器很棒。
  • 但是,如果您的项目是直接ADO,那么完成一项简单任务就是一个非常严重的变化。

CSV拆分

在此策略中,您将CSV字符串传递给SQL,无论是ad-hoc还是存储过程参数。 该字符串由值为UDF的表处理,该值将值作为单个列表返回。

  • 自SQL-2000以来,这一直是一个成功的策略
  • @TimSchmelter给出了csv拆分函数的一个很好的例子。
  • 如果你谷歌这里有数百篇文章从各种字符串长度的基础知识到性能分析的各个方面。

表值参数

在SQL 2008中,可以定义自定义“表类型”。 一旦定义了表类型,就可以在ADO中构造它并作为参数传递。

  • 这里的好处是它适用于更多场景而不仅仅是一个整数列表 – 它可以支持多个列
  • 强类型
  • 将字符串处理拉回到一个非常好的层/语言。
  • 这是一个相当大的主题,但SQL Server 2008(ADO.NET)中的表值参数是一个很好的起点。