使用MySQL中的单个语句以更高的值更新列

时间:2011-08-04 15:22:19

标签: mysql sql

我有一个第三方应用程序已从早期版本迁移到当前版本,并且在迁移期间,新列已添加到数据库中。此列表示外部测试用例标识符。表中有一个用于测试用例记录的唯一标识符,该标识符对用户是隐藏的。创建新版本的测试用例时,会向表中添加新记录。显然有一个新的id,但外部标识符保持不变,因此最终用户认为这是相同的测试用例。不是我的模特,但足够公平。

在迁移过程中,添加了该列,现在所有测试用例看起来都是id为零。哎呀。好吧,几乎所有,因为通过GUI添加了一些新案例并且它们具有正确的数字。并且启动其中一个测试用例实际上有第二个版本。我已修复该记录,因此它具有有效的外部ID。

以下是我桌子相关位的快照:

mysql> select id, version, tc_external_id from tcversions order by id limit 5;
+------+---------+----------------+
| id   | version | tc_external_id |
+------+---------+----------------+
| 9454 |       1 |              0 |
| 9455 |       1 |              5 |
| 9456 |       1 |              0 |
| 9457 |       1 |              0 |
| 9458 |       1 |              0 |
+------+---------+----------------+
5 rows in set (0.33 sec)

对于熟悉数据库的人,是的,这是TestLink 1.9.3。它是我们继承的修改后的1.7.4系统的迁移数据库。

我正在寻找一个MySQL UPDATE语句,它将让我更新tc_external_id,使得每条记录获得单调递增的数字,而不必求助于编写单独的bash / perl /执行N次更新的脚本。所以结果看起来如下:

mysql> select id, version, tc_external_id from tcversions order by id limit 5;
+------+---------+----------------+
| id   | version | tc_external_id |
+------+---------+----------------+
| 9454 |       1 |              6 |
| 9455 |       1 |              5 |
| 9456 |       1 |              7 |
| 9457 |       1 |              8 |
| 9458 |       1 |              9 |
+------+---------+----------------+
5 rows in set (0.33 sec)

这可能吗?我的SQL foo显然不能胜任这项任务,如果有人能指出我正确的FM,我很高兴RTM。

编辑:同事想出了以下解决方案

我的一位同事为我提供了解决方案,如果我自己这么说的话,这是非常讨厌的。格式化是我的,他把它作为一条长线。嘎。火焰消失,但确实有效。

REPLACE INTO tcversions 
  SELECT @r := id as id, 
         @r1 := version as version, 
         @r2 := summary as summary, 
         @r3 := importance as importance, 
         @r4 := author_id as author_id, 
         @r5 := creation_ts as creation_ts,
         @r6 := updater_id as updater_id, 
         @r7 := modification_ts as modification_id, 
         @r8 := active as active, 
         @r9 := is_open as is_open, 
         @r10 := execution_type as execution_type, 
         @c := @c + 1 as tc_external_id, 
         @r12 := layout as layout, 
         @r13 := status as status, 
         @r14 := preconditions as preconditions 
  FROM 
    (SELECT @r := '', 
            @r1 := '', 
            @r2 := '', 
            @r3 := '', 
            @r4 := '', 
            @r5 := '', 
            @r6 := '', 
            @r7 := '', 
            @r8 :='', 
            @r9 := '', 
            @r10 := '', 
            @r11 := '', 
            @r12 := '', 
            @r13 := '', 
            @r14 := '',  
            @c := max(tcversions.tc_external_id) from tcversions ) rc, 
    (SELECT id,
            version, 
            summary, 
            importance, 
            author_id, 
            creation_ts, 
            updater_id, 
            modification_ts, 
            active, 
            is_open, 
            execution_type, 
            tc_external_id, 
            layout, 
            status, 
            preconditions 
     FROM tcversions  WHERE tc_external_id = 0  ORDER BY id) k;

3 个答案:

答案 0 :(得分:2)

UPDATE tcversions SET tc_external_id = @id := IF( ISNULL( @id ), 1, @id + 1 )
    WHERE id = 0;

您可能希望将新的插入中已有的最高tc_external_id替换为1(@id的起始值)。

答案 1 :(得分:1)

供参考

我找到了答案here

SET @id = 5;
UPDATE tcversions
  SET tc_external_id = (SELECT @id := @id + 1)
  WHERE tc_external_id=0
  ORDER BY id;

答案 2 :(得分:0)

这看起来与top10查询有关。使用SQlite绘制草图:

sqlite> select a.id, a.version, count(*)
        from tcversions a, tcversions b
        where a.id >= b.id
        group by a.id;
9454|1|1
9455|1|2
9456|1|3
9457|1|4

问题是如何立即更新你的表格; - )