繁体   English   中英

将数组作为值传递到ado.net DBParameter中

[英]Pass an array as value in an ado.net DBParameter

我正在研究的项目有很多IN查询,例如:

SELECT something, anotherthing
FROM atable
WHERE something IN (value1, value2, value3)

这是在IN部分中具有3个参数的查询的示例,但是可以使用1或2或5或10或...参数执行相同的查询。 问题是每个查询在数据库中都有一个其他执行计划,使其变慢。

我想要这样的查询:

SELECT something, anotherthing
FROM atable
WHERE something IN (@value1, @value2, @value3)

或这个:

SELECT something, anotherthing
FROM atable
WHERE something IN (@values)

我用一些辅助函数完成了第一个查询,但是每个参数的数量仍然有不同的执行计划。 这可以用第二个解决。

将数组作为数据库参数传递的最佳方法是什么? 我正在使用Oracle和SQL Server,欢迎使用这两种解决方案。

对于SQL-Server,有两种常见的方法。 要避免的第三个选项是传入一个varchar并将其连接到一个带有IN的动态SQL语句中 - 这是一个清晰的注入攻击面。

合理的选择:

  • 传入varchar并使用UDF在分隔符上分割数据( 如本问题所示 ),可能是逗号,管道,制表符等。加入结果:

     SELECT something, anotherthing FROM atable a INNER JOIN dbo.SplitUDF(@values) udf ON udf.Value = a.something 
  • 使用表值参数 (SQL2008)并直接连接(避免使用UDF)

看看这些文章

这是使用XML类型创建列表的示例

--Split
DECLARE @textXML XML
DECLARE @data NVARCHAR(MAX), 
        @delimiter NVARCHAR(5)

SELECT  @data = 'A,B,C',
        @delimiter = ','

SELECT    @textXML = CAST('<d>' + REPLACE(@data, @delimiter, '</d><d>') + '</d>' AS XML)
SELECT  T.split.value('.', 'nvarchar(max)') AS data
FROM    @textXML.nodes('/d') T(split)

这段代码可以解决问题。 您可以创建自己的BuildQuery(???)函数。

    public void RemoveDependencies(int versionID, int[] deps)
    {
        if (versionID <= 0)
            throw new ArgumentException();
        if (deps == null)
            throw new ArgumentNullException();
        if (deps.Length <= 0)
            throw new ArgumentException();

        SqlCommand cmd = new SqlCommand();
        string query = "DELETE FROM Dependencies WHERE version_id = @VersionId AND dep_version_id IN (";
        int n = deps.Length;
        string key;
        for (int i = 0; i < n; i++)
        {
            if (deps[i] <= 0)
                throw new ArgumentException();
            key = String.Format("@dep{0}", i);
            query += key;
            cmd.Parameters.AddWithValue(key, deps[i]);
            if (i < n - 1)
            {
                 query += ", ";
            }
        }
        query += ")";
        cmd.Parameters.AddWithValue("@VersionId", versionID);
        cmd.CommandText = query;
        using (SqlConnection con = GetSqlConnection())
        {
            con.Open();
            cmd.Connection = con;
            if (cmd.ExecuteNonQuery() <= 0)
            {
                throw new ArgumentException("No rows affected! Illegal id.");
            }
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM