代码之家  ›  专栏  ›  技术社区  ›  Chris Cudmore

将多行更新到SQL表中

  •  2
  • Chris Cudmore  · 技术社区  · 16 年前

    假设有一个完全填充的数据字符串[n][3]myData数组。

    我想这样做:

    for (String[] row : myData)
    {
       SQL = "update mytable set col3 = row[2]
       where col1 = row[0] and col2=row[1];" 
    }
    

    显然,我遗漏了很多,但我想尽可能简洁地表达我的想法。

    有没有一种简单的方法可以在一个DB命令中实现这一点?

    编辑:
    鉴于该应用程序面向web,它必须是防注入的。参数化查询是我首选的方式。
    我正在使用MS-SQL Server 2005

    Multiple DB Updates:

    编辑:重新打开,因为这似乎是一个热门问题

    10 回复  |  直到 7 年前
        1
  •  7
  •   Kevin Berridge    16 年前

    这取决于您使用的数据库。如果您使用的是SQL Server 2008,则可以使用存储过程 TABLE parameters

    update mytable set mytable.col1 = @tbl.col1
      from mytable 
      inner join @tbl on mytable.col2 = @tbl.col2
    

    如果您使用的是SQLServer2005,那么可以使用XML。将值格式化为XML,然后使用XQuery语句(即“节点”和“值”)解析XML。这也可以在单个SQL语句中完成,并且不需要存储过程。

        2
  •  3
  •   Ted Elliott    16 年前

    如果您使用的是Sql Server,则可以使用SqlBulkCopy。您首先必须将数据放在DataTable中,这非常简单,因为您已经将其放在字符串数组中了。

    http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

        3
  •  1
  •   fmsf    16 年前

    for (String[] row : myData)
    {
       SQL += "update mytable set col3 = row[2]
       where col1 = row[0] and col2=row[1];" 
    }
    
    sqlDriver.doInsertQuery(SQL); // change this to your way of inserting into the db
    

    一次完成所有的任务。我不太擅长SQL,所以我会这样做。

    sql引擎将只按“;”拆分它并单独插入。不过,可以将其全部添加到字符串中。这与将包含多个更新/插入的大字符串复制到sql提示符中是一样的

        4
  •  1
  •   extraneon    16 年前

        5
  •  1
  •   Nick    16 年前

    如果您正在使用 Enterprise Library 在数据访问层中,您可以在.Net中创建事务,迭代过程调用,然后从.Net提交/回滚所有事务。

    DbTransaction transaction = connection.BeginTransaction();
    try
    {
        for (String[] row : myData)
        {
            ListDictionary params = new Specialized.ListDictionary();
            params.add("@col3", row[2]);
            params.add("@col1", row[0]);
            params.add("@col2", row[1]);
            executeNonQuery("myUpdateProcedure", params);
        }
    
        transaction.commit();
    
    }
    catch(Exception ex)
    {
        transaction.rollback();
        throw ex;
    }
    finally
    {
    
        connection.close();
    }
    
        6
  •  1
  •   cmsjr    16 年前

    如果出于任何原因,您不能使用上面建议的方法之一执行更新,那么下面效率极低的方法可能适合您。

    SQL = "Update myTable Set Col3 = Case " 
    for (String[] row : myData)
    {
       SQL += "When Col1 = " + Row[0] + " and Col2 = " + Row[1] + " then " + row[2] + " "   
    }
    SQL + = "Else Col3 end"  
    
        7
  •  1
  •   C B dkretz    7 年前

    也许(如果您使用的是Microsoft SQL Server…我不知道它是否存在于Oracle中,可能是)您可以使用带有更新的联接。可以对与另一个表联接的表声明更新。如果myData来自另一个表,则可以执行以下操作(语法不正确):

    UPDATE whatchanges wc INNER JOIN changes c ON <yourcondition>
    SET wc.col1 = c.newvalue
    WHERE ....
    

    (如果要应用“changes”表中的所有更改,则不必使用,当然,内部联接已经选择了正确的行)。

    当然,这种更新也有局限性。这是微软SQL专有的。因此,如果是您的情况,我建议您在MS web上查找它(关键字:更新和加入)

        8
  •  0
  •   EndangeredMassa    16 年前

    不是真的。您可以使用相同的循环创建字符串,然后将值作为参数传递,但这仍然是多个数据库命令。

    for each whatever
        sql += "UPDATE ... ;"
    end for
    execute (sql)
    
        9
  •  0
  •   theraccoonbear    16 年前

    我怀疑您将需要使用多个SQL语句。您可能会发现一个包装器来处理细节,但在它的下面,我可以想象它会为每个更新迭代运行一条SQL语句。

        10
  •  0
  •   Hafthor    16 年前

    发出不符合值表的更新:

    UPDATE myTable SET col3=c FROM myTable JOIN (
      SELECT 1 as a, 2 as b, 'value1' as c UNION ALL
      SELECT 3 as a, 4 as b, 'value2' as c -- etc...
    ) x ON myTable.col1=x.a AND myTable.col2=x.b
    

    // make one of these for each row
    String.Format("SELECT {0} as a, {1} as b, '{2}' as c", 
      row[0], row[1], row[2].Replace("'","''")) 
    
    // put it together
    string expr = "UPDATE myTable SET col3=c FROM myTable JOIN (" +
      String.Join(stringformatarray, " UNION ALL ") +
      ") x ON myTable.col1=x.a AND myTable.col2=x.b"
    

    或者您可以使用StringBuilder将其组合在一起。

    然后,当然,执行这个字符串。