0

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

                    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 性能...所以请通过提供一个替代想法来帮助我......有大约 1000 条记录要更新......

4

2 回答 2

1

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

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

这样你就只有 1 个 DB 调用。

于 2012-07-09T18:35:34.800 回答
1

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

更新:为了正确处理 status_bits 列中的现有值小于 4 个字符的情况,我们要确保在现有字符串只有 1 个字符长时替换第 5 个字符,而不是第 2 个字符。我们可以使用 CASE 表达式来进行测试。当我们至少有 4 个字符时,我们可以在前四个字符之后附加我们的(所需的)第 5 个字符。否则,我们需要将现有字符串“填充”为 4 个字符,然后再添加(所需的)第 5 个字符。(以前,该语句仅包含适用于长度至少为 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 没有STUFFSQL Server 提供的更紧凑的功能。)


更新:处理长度小于 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 个位置的字符的值需要在两个单独的位置参数中提供。

笔记:

于 2012-07-09T18:47:09.370 回答