insert ... select ... on duplicate key update + delete obsolete rows

时间:2014-09-29 16:43:04

标签: mysql sql insert-update

我需要更新一个表,其中包含可以添加/更新/删除数据的表中预先计算的值。

我可以用

insert into precalculated(...)
select ... from ...
on duplicate key update ...

添加/更新预先计算的表但是有一个优化方法来删除过时的行吗?

4 个答案:

答案 0 :(得分:1)

我认为您应该创建一个存储过程,当且仅当记录满足条件时才会删除相关表的数据。

您的问题中没有足够的信息来设计程序,但我可以给您一些例子:

delimiter $$
create procedure delete_orphans()
begin
    declare id_orphan int;
    declare done int default false;
    declare cur_orphans cursor for
        select distinct d.id
        from data as d
            left join precalculated as p on d.id = p.id
        where p.id is null;
    declare continue handler for not found set done = true;
    open cur_orphans;
    loop_delete_orphans: loop
        fetch cur_orphans into id_orphan;
        if done then
            leave cur_orphans;
        end if;
        delete from data where id = id_orphan;
    end loop;
    close cur_orphans;
end$$
delimiter ;

此过程将删除data表中precalculated表中至少没有一个相关行的每一行。

当然,这种方法可能不合适,因为它会逐个删除行,但正如我所说,这只是一个例子。您可以根据自己的需要进行自定义。

如果需要,您可以从触发器调用此过程(使用call delete_orphans())。

希望这有帮助。

答案 1 :(得分:1)

由于您总是添加或更新这些其他表中存在的行,并且您想要删除任何不存在的行,为什么不这样做:

DELETE FROM precalculated
insert into precalculated(...)
select ... from ...
on duplicate key update ...

始终开始清洁意味着您以后不必担心孤儿。

答案 2 :(得分:1)

您可以在维护precalculated的主表上添加插入,删除和更新的触发器。

插入或更新时,可以使用相同的代码计算值并发出replace into precalculated (...) values (...)

删除它时可能相同,另外还要删除precalculated中孤儿的行。在这里要聪明并使用原始删除中的值来查询precalculated的孤儿,而不是进行表扫描。

答案 3 :(得分:0)

我可能已经使用重命名找到了我的解决方案。

所以基本上,我会做一个简单的插入选择到临时表,然后

rename precalculated to precalculated_temprename, precalculated_temp to precalculated, precalculated_temprename to precalculated_temp;
truncate precalculated_temp;

需要一些测试,但似乎重命名操作是快速和原子的。