是否可以将ID的集合作为ADO.NET SQL参数发送?

时间:2008-09-22 12:19:10

标签: .net sql ado.net

EG。我可以写这样的代码:

public void InactiveCustomers(IEnumerable<Guid> customerIDs)
{
    //...
    myAdoCommand.CommandText =
        "UPDATE Customer SET Active = 0 WHERE CustomerID in (@CustomerIDs)";
    myAdoCommand.Parameters["@CustomerIDs"].Value = customerIDs;
    //...
}

我知道的唯一方法是加入我的IEnumerable,然后使用字符串连接来构建我的SQL字符串。

6 个答案:

答案 0 :(得分:17)

通常,执行此操作的方法是传入逗号分隔的值列表,并在存储过程中解析列表并将其插入临时表,然后可以将其用于连接。从 Sql Server 2005 开始,这是处理需要保存数组的参数的标准做法。

这是一篇关于处理这个问题的各种方法的好文章:

Passing a list/array to an SQL Server stored procedure

但对于 Sql Server 2008 ,我们最终将表变量传递给过程,首先将表定义为自定义类型。

本文中对此(以及更多2008功能)有一个很好的描述:

Introduction to New T-SQL Programmability Features in SQL Server 2008

答案 1 :(得分:5)

您可以使用SQL 2008。它还没有很长时间,但可以使用。

答案 2 :(得分:2)

如前所述[{3}},Erland Sommarskog撰写了一系列关于这一主题的文章(链接到下面)。这些文章非常详尽,可以作为参考资料。虽然它们特定于SQL Server(T-SQL),但所提到的一些技术也可能适用于其他RDBMS(例如使用XML数据类型):

答案 3 :(得分:1)

您可以使用xml参数类型:

CREATE PROCEDURE SelectByIdList(@productIds xml) AS

DECLARE @Products TABLE (ID int) 

INSERT INTO @Products (ID) SELECT ParamValues.ID.value('.','VARCHAR(20)')
FROM @productIds.nodes('/Products/id') as ParamValues(ID) 

SELECT * FROM 
    Products
INNER JOIN 
    @Products p
ON    Products.ProductID = p.ID

http://weblogs.asp.net/jgalloway/archive/2007/02/16/passing-lists-to-sql-server-2005-with-xml-parameters.aspx

答案 4 :(得分:-3)

不。参数就像服从first normal form的SQL值一样,基本上只有一个......

正如您可能知道的那样,生成SQL字符串是一项有风险的事情:您可以向SQL injection attack开放。只要你正在处理真正的GUID,你应该没问题,但除此之外,你需要确保清理你的输入。

答案 5 :(得分:-3)

您无法将列表作为单个SQl参数传递。您可以将GUID(',')作为GUID,例如“0000-0000-0000-0000,1111-1111-1111-1111”,但这对数据库开销很高,而且实际上是次优的。并且您必须将整个字符串作为单个连接动态语句传递,您不能将其作为参数添加。

问题:

您从哪里获得代表不活跃客户的ID列表?

我的建议是以稍微不同的方式解决问题。将所有逻辑移动到数据库中,如:

    Create procedure usp_DeactivateCustomers 
    @inactive varchar(50) /*or whatever values are required to identify inactive customers*/
    AS    
    UPDATE Customer SET c.Active = 0 
    FROM Customer c JOIN tableB b ON c.CustomerID = b.CustomerID 
    WHERE b.someField = @inactive

并将其称为存储过程:

public void InactiveCustomers(string inactive)
{
    //...
    myAdoCommand.CommandText =
        "usp_DeactivateCustomers";
    myAdoCommand.Parameters["@inactive"].Value = inactive;
    //...
}

如果数据库中存在GUID列表,为什么我需要:找到它们;把它们放在通用列表中;将列表展开为CSV / XML / Table变量,只是为了再次将它们呈现给DB ?????他们已经在那里了!我错过了什么吗?