使用存储过程保留最新的3条记录,删除所有记录

时间:2018-04-04 07:39:40

标签: mysql stored-procedures

我正在尝试删除除最后3个以外的所有记录。

每个记录都有一个名为slug和version的列。

这里的slug名称可以相同,但版本号是唯一的。

For example.
slug          version
template1       1
template1       2
template1       3
template1       4
template1       5
template1       6

我想保留最后3条记录4,5,6并删除其余的1,2,3

使用存储过程尝试了以下方法。

CREATE DEFINER=`root`@`localhost` PROCEDURE `deleteall`()
BEGIN
    DELETE FROM `table_name` WHERE slug='template1' and version IN( 
  SELECT version 
  FROM ( 
    SELECT version
    FROM `table_name` 
    ORDER BY version asc 
    LIMIT 3 offset 3
  ) tbl123
);    

END

提前致谢。

1 个答案:

答案 0 :(得分:1)

将asc更改为desc并将限制增加到大数

create table t(slug varchar(20),   version int);
insert into t values
('template1'  ,     1),
('template1'  ,     2),
('template1'  ,     3),
('template1'  ,     4),
('template1'  ,     5),
('template1'  ,     6),
('template1'  ,     7);


delete from t where version in
(
select version from
(
SELECT version
    FROM t 
    ORDER BY version desc 
    LIMIT 999999 offset 3
) s
);

+-----------+---------+
| slug      | version |
+-----------+---------+
| template1 |       5 |
| template1 |       6 |
| template1 |       7 |
+-----------+---------+
3 rows in set (0.00 sec)

如果要将slug作为参数传递给存储过程

drop table if exists t;
create table t(slug varchar(20),   version int);
insert into t values
('template1'  ,     1),
('template1'  ,     2),
('template1'  ,     3),
('template1'  ,     4),
('template1'  ,     5),
('template1'  ,     6),
('template1'  ,     7),
('template2'  ,     1),
('template2'  ,     2),
('template2'  ,     3),
('template2'  ,     4),
('template3'  ,     1),
('template3'  ,     2),
('template3'  ,     3);

drop procedure if exists p;
delimiter $$
create procedure p(inslug varchar(100))
begin
delete from t where slug = inslug and version in
#select * from t where slug = inslug and version in
(
select version from
(
SELECT version
    FROM t 
    where slug = inslug
    ORDER BY version desc 
    LIMIT 999999 offset 3
) s
);
end $$
delimiter ;

MariaDB [sandbox]> call p('template2');
Query OK, 1 row affected (0.02 sec)

MariaDB [sandbox]> select * from t;
+-----------+---------+
| slug      | version |
+-----------+---------+
| template1 |       1 |
| template1 |       2 |
| template1 |       3 |
| template1 |       4 |
| template1 |       5 |
| template1 |       6 |
| template1 |       7 |
| template2 |       2 |
| template2 |       3 |
| template2 |       4 |
| template3 |       1 |
| template3 |       2 |
| template3 |       3 |
+-----------+---------+
13 rows in set (0.00 sec)

MariaDB [sandbox]> call p('template1');
Query OK, 4 rows affected (0.02 sec)

MariaDB [sandbox]> select * from t;
+-----------+---------+
| slug      | version |
+-----------+---------+
| template1 |       5 |
| template1 |       6 |
| template1 |       7 |
| template2 |       2 |
| template2 |       3 |
| template2 |       4 |
| template3 |       1 |
| template3 |       2 |
| template3 |       3 |
+-----------+---------+
9 rows in set (0.00 sec)

MariaDB [sandbox]> call p('template3');
Query OK, 0 rows affected (0.00 sec)

MariaDB [sandbox]> select * from t;
+-----------+---------+
| slug      | version |
+-----------+---------+
| template1 |       5 |
| template1 |       6 |
| template1 |       7 |
| template2 |       2 |
| template2 |       3 |
| template2 |       4 |
| template3 |       1 |
| template3 |       2 |
| template3 |       3 |
+-----------+---------+
9 rows in set (0.00 sec)

如果你想删除所有slug(通过迭代光标)或只删除一个

drop procedure if exists p;
delimiter $$
create procedure p(inslug varchar(100))
begin
declare vslug varchar(100) default false;
declare done int;
declare cur  cursor for select distinct slug from t;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
if inslug <> 'all' then
delete from t where slug = inslug and version in
#select * from t where slug = inslug and version in
(
select version from
(
SELECT version
    FROM t 
    where slug = inslug
    ORDER BY version desc 
    LIMIT 999999 offset 3
) s
);
else
 open cur;

 read_loop: loop
        fetch cur into vslug;
        if done then leave read_loop; end if;
        delete from t where slug = vslug and version in
        #select * from t where slug = vslug and version in
        (
        select version from
        (
        SELECT version
        FROM t 
        where slug = vslug
        ORDER BY version desc 
        LIMIT 999999 offset 3
        ) s
        );

 end loop;
 close cur;
end if;
end $$
delimiter ;

并通过电话(&#39;所有&#39;)或致电(特定slu)来运行