选择更新许多值的更好解决方案

时间:2012-07-09 18:30:56

标签: java mysql database-design

我想根据不同的情况更新列中的一些值..... 该表具有以下细节,如.....

                    Date               date
                    period             int
                    subcode            varchar(3)
                    status_bits        varchar(100)
                    // status bits resemble an information based code based...the data usually stored are  2343211 where each value in digits represent an information.....

现在我必须根据不同的日期和时段更新这些值.... 现在考虑java program ......

我已将详细信息存储在java中的相应变量中,如..

                   java.util.Date date[];
                   int period[];
                   String subcode[];

                   // Here for an index i , they share the same values within a row.....

如果我想以这样的方式更新它,我想要在varchar中更改不同日期,时段和子码的第5个字母(组合)..... 现在......我现在表现得像这样...

     Connection con;
     preparedStatement ps;
     String bitstatus;



     for(i=0; i < noofupdates; i++)
     {
           ps = con.prepareStatement("select status_bits from tablename where Date = ? AND period = ? AND subcode = ? limit 0,1");
           ps.setDate(1,date[i]);
           ps.setInt(2,period[i])'
           ps.setString(3,subcode[i]);

           rs=ps.executeQuery();
           while(rs.next())
           {

                 bitstatus = rs.getString(1);
                 // performed operation to update the bit.....
                 ps=con.prepareStatment("update status_bits correspondind to the same date,field and subcode");

                 ps.executeUpdate();
           }

     }

现在我假设您从程序中了解到我想根据位操作常见的不同日期和时段更新表中的status_bits ......现在我真的知道了这些方法是锤击大量查询并严重影响mysql性能...所以PLZ通过提供一个很多替代的想法来帮助我.......有大约1000条记录要更新.........

2 个答案:

答案 0 :(得分:1)

您首先从数据库中读取一些数据(status_bits),然后根据检索到的记录数多次调用多个数据库。

相反,为什么不编写一个存储过程,它将日期,句点和子代码作为参数并在SP本身中执行整个逻辑?

这样你只有1个DB呼叫。

答案 1 :(得分:1)

如果您知道您希望将status_bits字符串的第5个位置设置为给定(日期,期间,子代码)的特定值,则可以避免SELECT并仅执行更新。

更新:为了正确处理status_bits列中现有值小于4个字符的情况,我们要确保在现有字符串为0时替换第5个字符,而不是第2个字符。只有1个字符长。我们可以使用CASE表达式来进行测试。当我们至少有4个字符时,我们可以在前四个字符后追加我们的(所需的)第5个字符。否则,在添加我们的(所需的)第5个字符之前,我们需要将现有字符串“填充”为4个字符。 (以前,该语句仅包含适用于现有字符串的表达式,其长度至少为4个字符。)

UPDATE tablename
   SET status_bits = 
       CASE WHEN CHAR_LENGTH(status_bits >= 4
         THEN CONCAT(LEFT(status_bits,4), ?, SUBSTR(status_bits,6))
         ELSE CONCAT(RPAD(status_bits,4), ? )
         END
 WHERE `Date` = ? AND period = ? AND subcode = ? 

(如果您不想更新所有匹配的行,可以添加LIMIT子句,但如果要更新所有匹配的行,则不需要这样做。如果(date,period,subcode)是唯一的,则您将匹配最多一行。)

还可以根据其他条件设置status_bits的第5个位置,例如,通过向where子句添加谓词,或者在SET中添加CASE表达式(或IF函数)。

UPDATE tablename
   SET status_bits = CONCAT(LEFT(status_bits,4)
                     , IF(SUBSTR(status_bits,1,1 = '1', ?, SUBSTR(status_bits,5,1))
                     , SUBSTR(status_bits,6))
 WHERE `Date` = ? AND period = ? AND subcode = ? 

相当于:

UPDATE tablename
   SET status_bits = CONCAT(LEFT(status_bits,4), ?, SUBSTR(status_bits,6))
 WHERE `Date` = ? AND period = ? AND subcode = ? 
   AND SUBSTR(status_bits,1,1) = '1'

此方法将减少您正在运行的查询数量的一半(减少到数据库的往返次数),并避免您必须返回整个status_bits列。

(不幸的是,用于替换varchar列的第5个字符的SQL文本有点不实用,因为MySQL没有SQL Server提供的更紧凑的STUFF函数。)


更新:处理长度小于4个字符的现有status_bits字符串所需的更复杂的表达式...)

UPDATE tablename
   SET status_bits = 
       CASE WHEN CHAR_LENGTH(status_bits) >= 4
            THEN CONCAT(LEFT(status_bits,4), ? , SUBSTR(status_bits,6))
            ELSE CONCAT(RPAD(status_bits,4,' '), ? )
       END
 WHERE `Date` = ? AND period = ? AND subcode = ?

注意:在该SQL语句中,要放置在第5位的字符值需要在两个单独的位置参数中提供。

注: