【问题标题】:SQL UPDATE Loop Non-Sequential KeysSQL UPDATE 循环非顺序键
【发布时间】:2009-11-03 14:50:40
【问题描述】:

我正在编写一个 C# 应用程序,它将更新 SQL Server 数据库中的字段。我正在测试的当前算法只是从“状态”字段中提取数据,将每个值存储在 ArrayList 中,将其大写,然后将其写回数据库。我的逻辑有问题。

我将所有值拉入 ArrayList 并将它们大写。这工作正常。我现在有一个数组,例如,100 个值(即 myArray[0] - myArray[99] )。然后我使用FOR 循环将值写回数据库:

for (int i = 0; i <= (myArray.Count - 1); i++)
{
   SqlCommand myCommand = 
      new SqlCommand("UPDATE myList SET State = '" + recordArray[i].ToString() + 
                     "' WHERE uniqueID = '" + (i + 1) + "'", dbConnection);
   myCommand.ExecuteNonQuery();
}

我在上面的例子中使用了“uniqueID”来根据主键放置这些值。但是,问题在于主键几乎是连续的;序列中有一些缺失的数字。因此,即使我有我需要的确切数量的值,并且它们在数组中以正确的顺序被推回数据库,一旦我在序列中达到一个间隔,其余的数据就会被放置在错误的领域。我知道这是我逻辑上的失误,但我不知道如何确保正确放置每个单独的值。

提前感谢您的帮助。

【问题讨论】:

    标签: c# sql sql-server sql-update


    【解决方案1】:

    这里有很多问题......

    1. 永远不要不要使用这样的动态 SQL。如果您的某个“状态”中有撇号怎么办?
    2. 除非这是 .Net 1.0 或 1.1,否则不应使用 ArrayList。请改用System.Collections.Generic.List&lt;string&gt;。
    3. 不要创建 99 个 SqlCommand 对象。创建1 SqlCommand 对象,并通过循环在每次迭代时更新参数值。
    4. 使用using 语句创建您的SqlCommand(更重要的是SqlConnection)对象,以确保在引发异常时及时释放非托管资源。
    5. 最重要的是,当你意识到你可以在一个 sql 语句中更新多条记录时,这一切都变得毫无意义,而且该 sql 有一个非常简单的“UPPER”函数。

    因为看起来您可以使用正确方法的示例来构建此类查询,所以我暂时假设 #5 在某种程度上不是一个选项,并且您确实需要将所有这些数据拉下来到应用程序,然后逐条记录更新它(提示:你不这样做)。以下是您应该如何构建该代码:

    using (SqlConnection cn1 = new SqlConnection("connection string here")) //inbound data
    using (SqlCommand cmd1 = new SqlCommand("SELECT uniqueid, State FROM myList", cn1)) 
    using (SqlConnection cn2 = new SqlConnection("connection string here"))
    using (SqlCommand cmd2 = new SqlCommand("UPDATE myList SET State= @State WHERE uniqueID= @ID", cn2))
    {
        SqlParameter StateParam = cmd2.Parameters.Add("@State", SqlDbType.VarChar, 50);
        SqlParameter IDParam = cmd2.Parameters.Add("@ID", SqlDbType.Int);
    
        cn1.Open();
        cn2.Open();
    
        using (SqlDataReader rdr = cmd1.ExecuteReader())
        {
            while (rdr.Read())
            {
                StateParam.Value = rdr["State"].ToString().ToUpper();
                IDParam.Value    = rdr["uniqueID"];
                cmd2.ExecuteNonReader();
            }
        }
    }
    

    请注意,这只是为了演示using 块和参数化查询。您应该不使用此代码。相反,请仔细看看我的第 5 点。这可以而且应该全部在单个 sql UPDATE 语句中完成。

    【讨论】:

    • +1 是的,你是对的 - 这段代码很糟糕 - 希望我能不止一次地支持你的答案!
    • 非常感谢您的帮助。我真的在寻找正确的方法来做到这一点,因为我知道我正在走“hacky”路线,而且效果很好。
    • 我现在可以使用 UPDATE 命令。显然问题在于我对 UPDATE 语法不熟悉。但是,您有关处理 SQL 的其他 cmet 使我对最佳实践有了更多的了解。再次感谢。
    • 哇 - 我和 Marc 在一起 - 我希望我能不止一次地支持这个答案。地理 - 假定用户输入的任何内容都不应直接插入 SQL 命令。事实上,为了安全起见,您可能希望 A) 始终使用参数化查询(以避免 SQL 注入攻击)和 B) 始终 HTMLEncode 任何请求参数,然后再将它们反射回页面(以避免跨站点脚本攻击)。
    • 感谢大家的帮助。我一直在使用您在此处所说的内容来研究通过 C# 与 SQL Server 交互的正确方法,并意识到我的做法是多么错误(和危险)。
    【解决方案2】:

    除非您只是将其作为练习,否则您知道可以直接执行更新吗?

    UPDATE myList SET State = Upper(State)
    

    【讨论】:

    • 这是一个练习,但它旨在学习如何以正确的方式通过 C# 与 SQL Server 交互。感谢您指出这一点!
    【解决方案3】:

    您需要获取相同行的主键值,并将其与数据一起跟踪,以便最终更新正确的行。

    【讨论】:

    • 谢谢!我认为这是其中的一部分,乔尔的上述解决方案也包括在内。
    猜你喜欢
    • 1970-01-01
    • 2017-03-04
    • 2011-11-30
    • 2023-03-20
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-20
    相关资源
    最近更新 更多