重新组合复合唯一约束中的键

时间:2016-03-05 17:23:56

标签: mysql database

我有一个类似于以下内容的表:

| id | sub_id | fk_id |
|----|--------|-------|
| 1  | 1      | 1     |
| 2  | 2      | 1     |
| 3  | 3      | 1     |
| 4  | 4      | 1     |
| 5  | 5      | 1     |
| 6  | 1      | 2     |
| 7  | 2      | 2     |
| 8  | 3      | 2     |
| 9  | 4      | 2     |
| 10 | 5      | 2     |

在此表中,id是主键,sub_idfk_id构成复合唯一键,其中fk_id是另一个表中的主键。< / p>

我发现自己处于需要能够删除表中行的情况,但是重新编号sub_id以便没有任何间隙,例如移除(1, 1, 1)以及fk_id=1各自sub_id重新编号为1,2,3,4等的所有行

我还需要能够一次删除一行或多行,然后触发重新编号(因为我认为只要一次就足够多次尝试重新编号,效率很低)。但是,fk_id的每个值最多有60行,但fk_id可能有数千个不同的值。

我应该如何进行重新编号?我认为某种INSERT ... SELECT查询,但我无法理解它应该如何工作。

2 个答案:

答案 0 :(得分:0)

您可以使用此查询对给定fk_id的行重新编号:

select t_renum.*, count(t_lower.id) as new_sub_id
from mytable t_renum
join mytable t_lower
    on  t_lower.fk_id = t_renum.fk_id
    and t_lower.id <= t_renum.id
where t_renum.fk_id = @renumber_fk_id
group by t_renum.id

结果可以与原始表一起进行更新,如下所示:

update mytable t
join (
    select t_renum.*, count(t_lower.id) as new_sub_id
    from mytable t_renum
    join mytable t_lower
        on  t_lower.fk_id = t_renum.fk_id
        and t_lower.id <= t_renum.id
    where t_renum.fk_id = @renumber_fk_id
    group by t_renum.id 
) t_renum using (id)
set t.sub_id = t_renum.new_sub_id

sqlfiddle

答案 1 :(得分:0)

在深入挖掘之后,我发现另一个非常简单的answer并且避免了在许多类似问题中推荐的新表的需要。我把它转换成了一个更符合我需求的存储过程:

DELIMITER //
CREATE PROCEDURE reindex (IN fk_key INT UNSIGNED)
BEGIN
    SET @num := 0;

    UPDATE example
        SET sub_id = (@num := @num + 1)
        WHERE fk_id = fk_key
        ORDER BY id;
END //
DELIMITER ;