【问题标题】:Is it possible to send a collection of ID's as a ADO.NET SQL parameter?是否可以将 ID 集合作为 ADO.NET SQL 参数发送?
【发布时间】:2008-09-22 12:19:10
【问题描述】:

例如。我可以写这样的代码吗:

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

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

【问题讨论】:

    标签: .net sql ado.net


    【解决方案1】:

    通常,您执行此操作的方式是传入一个逗号分隔的值列表,然后在您的存储过程中解析该列表并将其插入到一个临时表中,然后您可以将其用于连接。从 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

    【讨论】:

    【解决方案2】:

    您可以使用SQL 2008。出来的时间不长,但是已经可以使用了。

    【讨论】:

      【解决方案3】:

      正如in a comment 所提到的,Erland Sommarskog 写了一系列关于这个主题的文章(链接到下面)。文章很透彻,可以作为参考资料。虽然它们特定于 SQL Server (T-SQL),但其中提到的一些技术也可能适用于其他 RDBMS(例如使用 XML 数据类型):

      【讨论】:

        【解决方案4】:

        可以使用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

        【讨论】:

          【解决方案5】:

          不。参数就像是遵循first normal form的SQL值,基本上只能有一个……

          您可能知道,生成 SQL 字符串是有风险的业务:您让自己对SQL injection attack 敞开大门。只要您处理真正的 GUID,您应该没问题,但否则您需要确保清理您的输入。

          【讨论】:

            【解决方案6】:

            您不能将列表作为单个 SQl 参数传递。您可以 string.Join(',') 诸如“0000-0000-0000-0000, 1111-1111-1111-1111”之类的 GUIDS,但这会增加数据库开销并且确实不是最佳的。而且您必须将整个字符串作为单个连接的动态语句传递,您不能将其添加为参数。

            问题:

            您从哪里获得代表不活跃客户的 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 ?????他们已经在那里了!我错过了什么吗?

            【讨论】:

            • 由于您回答中的第一个陈述而被否决,这通常不是真的。我同意你的问题结束时的建议,虽然......在某些情况下,确实有可能在数据库中做所有事情,所以如何传输列表的问题可能永远不会出现完全没有。
            猜你喜欢
            • 1970-01-01
            • 2015-06-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-04-13
            • 2014-05-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多