我使用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中删除。 当我使用相同的算法插入或更新数据库时,一切正常。 有人知道这是什么问题吗?
答案 0 :(得分:9)
您不能在常规TSQL中执行此操作,因为服务器会将@idList
视为恰好包含逗号的单个值。但是,如果您使用List<int>
,则可以使用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))
答案 1 :(得分:3)
根据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, ',')));
答案 2 :(得分:1)
我想更多地讨论这个问题。这似乎属于“如何获取多行数据到SQL ”的主题。在@Kate的情况下,她正在尝试DELETE-WHERE-IN,但是这个用户案例的有用策略与UPDATE-FROM-WHERE-IN或INSERT INTO-SELECT FROM的策略非常相似。我看到它的方式有几个基本策略。
这是最古老,最基本的方式。你做一个简单的“SELECT * FROM MyTable WHERE ID IN(”+ someCSVString +“);”
正如@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 )
在此策略中,您将CSV字符串传递给SQL,无论是ad-hoc还是存储过程参数。该字符串由值为UDF的表处理,该值将值作为单个列表返回。
在SQL 2008中,可以定义自定义“表类型”。一旦定义了表类型,就可以在ADO中构造它并作为参数传递。