MySQL没有RowNum,那我该怎么按“行”查询或删除数据?

众所周知,MySQL是没有rowNum隐藏列的。陈哈哈教你在没有主键自增ID的情况下,如何根据“行”为条件来查询或删除数据。如:查询或删除第5-10行的数据。

我们都知道,在Oracle中,有一列隐藏列 rowNum,代表 table 中固定的行值,不会随着数据的改变而改变。rowNum多用来分页, 也可以通过rowNum来删除指定行,比如删除第6到第10行[6,10],SQL如下:

delete from t where rowNum between 6 and 10;

但在MySQL中,是没有rowNum这个关键词的,那么,假如我的表没有自增主键id,或者说我用的主键是无序UUID。且我有个需求:删除第6到第10行的数据,该怎么操作呢?

在日常开发中,不知道你是否遇到过查询条件为 “行” 的时候呢?其实,是有很多场景会使用到的。

比如前段时间,我们业务中有一张应用信息表,这张表是同事小刘直接用csv文件导入的,会有其他公司的人对这些数据进行人工分析,导入时并没有设置自增主键,小刘没有想到已经给自己留下了隐患。

扫描二维码关注公众号,回复: 11479805 查看本文章

这张表有20w行数据,其中第8w条 - 15w条是多余的,也不能重新导,因为可能其他公司的同事已经在处理了,这时该怎么删除多余数据呢?

为了不被领导邀请爬山,他找到我求救。

小刘:“哈哥,救命救命,这MySQL没有自增主键,我咋删除第[8w,15w]的数据啊?”
陈哈哈:“啊?MySQL又没有rowNum,那咋搞啊?我不会,不会~”

小刘:“一顿串儿!哈哥快来”
陈哈哈:“哎呀,我这活儿急得一匹,下午再说吧。”

小刘:“今儿晚上,望京小腰,不请我是你儿子!”
陈哈哈:“什么串儿串儿的,都是兄弟,说的就跟我怕你吹牛B不请似的,来吧来吧,一起看看咋处理。”
小刘:“……”

其实,在MySQL中确实没有rownum伪列,但我们可以自己写函数定义。线上数据不方便,下面我拿一些测试数据来举例吧(15条),如下

mysql> select * from t_student;
+------------+-----+-----+-------+----------+-----------+
| NAME       | SEX | AGE | CLASS | GRADE    | HOBBY     |
+------------+-----+-----+-------+----------+-----------+
| 陈哈哈     | 男  |  15 | 18班  | 9年级1   | 上网      |
| 扈亚鹏     | 男  |  15 | 18班  | 9年级1   | 美食      |
| 徐立楠     | 女  |  14 | 18班  | 9年级1   | 阅读      |
| 陈子凝     | 女  |  15 | 18班  | 9年级1   | 看电影    |
| 刘晓莉     | 女  |  14 | 18班  | 9年级1   | 金希澈    |
| 陈哈哈1    | 男  |  15 | 18班  | 9年级2   | 上网      |
| 扈亚鹏1    | 男  |  15 | 18班  | 9年级2   | 美食      |
| 徐立楠1    | 女  |  14 | 18班  | 9年级2   | 阅读      |
| 陈子凝1    | 女  |  15 | 18班  | 9年级2   | 看电影    |
| 刘晓莉1    | 女  |  14 | 18班  | 9年级1   | 金希澈    |
| 陈哈哈2    | 男  |  15 | 18班  | 9年级2   | 上网      |
| 扈亚鹏2    | 男  |  15 | 18班  | 9年级2   | 美食      |
| 徐立楠2    | 女  |  14 | 18班  | 9年级2   | 阅读      |
| 陈子凝2    | 女  |  15 | 18班  | 9年级2   | 看电影    |
| 刘晓莉2    | 女  |  14 | 18班  | 9年级1   | 金希澈    |
+------------+-----+-----+-------+----------+-----------+
15 rows in set (0.00 sec)

如何查询这些的数据的行值呢?SQL如下:

-- 在没自增主键情况下,查询数据行(rownum),行号
select @rownum:=@rownum+1 AS rownum,`NAME`,`SEX`,`CLASS`,`GRADE`
 from t_student ,(SELECT @rownum:=0) r;

查询结果如下:

mysql> select @rownum:=@rownum+1 AS rownum,`NAME`,`SEX`,`CLASS`,`GRADE` from t_student ,(SELECT @rownum:=0) r;
+--------+------------+-----+-------+----------+
| rownum | NAME       | SEX | CLASS | GRADE    |
+--------+------------+-----+-------+----------+
|      1 | 陈哈哈     | 男  | 18班  | 9年级1   |
|      2 | 扈亚鹏     | 男  | 18班  | 9年级1   |
|      3 | 徐立楠     | 女  | 18班  | 9年级1   |
|      4 | 陈子凝     | 女  | 18班  | 9年级1   |
|      5 | 刘晓莉     | 女  | 18班  | 9年级1   |
|      6 | 陈哈哈1    | 男  | 18班  | 9年级2   |
|      7 | 扈亚鹏1    | 男  | 18班  | 9年级2   |
|      8 | 徐立楠1    | 女  | 18班  | 9年级2   |
|      9 | 陈子凝1    | 女  | 18班  | 9年级2   |
|     10 | 刘晓莉1    | 女  | 18班  | 9年级1   |
|     11 | 陈哈哈2    | 男  | 18班  | 9年级2   |
|     12 | 扈亚鹏2    | 男  | 18班  | 9年级2   |
|     13 | 徐立楠2    | 女  | 18班  | 9年级2   |
|     14 | 陈子凝2    | 女  | 18班  | 9年级2   |
|     15 | 刘晓莉2    | 女  | 18班  | 9年级1   |
+--------+------------+-----+-------+----------+
15 rows in set (0.00 sec)

可以看到查询到的行号,那我该怎么通过上面查到的rownum行来进行删除呢?其实这个想法是行不通的,因为上面的rownum就是一个展示值,是没有其他实际效果的。

但是,我可以通过找到表中的唯一列(如UUID、MD5、包名、身份证ID),通过范围条件查询rownum,从而找到需要删除的唯一键集合,比如在这张表中存在唯一键是“NAME”,那么我通过查到第[6,10]行数据的唯一键“NAME”,从而通过子查询来删除,(这里是把人名后有“1”的删除)。SQL如下:

我们先看一下第[6,10]行数据,SQL如下:

-- 查询第6到第10行数据。
SELECT * from (select @rownum:=@rownum+1 AS rownum,`NAME`,`SEX`,`CLASS`,`GRADE` from 
  t_student ,(SELECT @rownum:=0) r) t where t.rownum between 6 and 10;

返回结果:

mysql> SELECT * from (select @rownum:=@rownum+1 AS rownum,`NAME`,`SEX`,`CLASS`,`GRADE` from t_student ,(SELECT @rownum:=0) r) t
    ->  where t.rownum between 6 and 10;
+--------+------------+-----+-------+----------+
| rownum | NAME       | SEX | CLASS | GRADE    |
+--------+------------+-----+-------+----------+
|      6 | 陈哈哈1    | 男  | 18班  | 9年级2   |
|      7 | 扈亚鹏1    | 男  | 18班  | 9年级2   |
|      8 | 徐立楠1    | 女  | 18班  | 9年级2   |
|      9 | 陈子凝1    | 女  | 18班  | 9年级2   |
|     10 | 刘晓莉1    | 女  | 18班  | 9年级1   |
+--------+------------+-----+-------+----------+
5 rows in set (0.00 sec)

下面我们来删除掉`NAME`中包含"1"的数据,也就是第6到第10行。

-- 以行为条件删除数据
DELETE from t_student where `NAME` in (SELECT `NAME` from 
  (select @rownum:=@rownum+1 AS rownum,`NAME`,`SEX`,`CLASS`,`GRADE` from t_student ,(SELECT @rownum:=0) r) t
   where t.rownum between 6 and 10);
mysql> DELETE from t_student where `NAME` in (SELECT `NAME` from (select @rownum:=@rownum+1 AS rownum,`NAME`,`SEX`,`CLASS`,`GRADE` from t_student ,(SELECT @rownum:=0) r) t where t.rownum between 6 and 10);
Query OK, 5 rows affected (0.07 sec)

再次查询,NAME中包含“1”的那5行数据已经被成功删除。

mysql> select @rownum:=@rownum+1 AS rownum,`NAME`,`SEX`,`CLASS`,`GRADE` from t_student ,(SELECT @rownum:=0) r;
+--------+------------+-----+-------+----------+
| rownum | NAME       | SEX | CLASS | GRADE    |
+--------+------------+-----+-------+----------+
|      1 | 陈哈哈     | 男  | 18班  | 9年级1   |
|      2 | 扈亚鹏     | 男  | 18班  | 9年级1   |
|      3 | 徐立楠     | 女  | 18班  | 9年级1   |
|      4 | 陈子凝     | 女  | 18班  | 9年级1   |
|      5 | 刘晓莉     | 女  | 18班  | 9年级1   |
|      6 | 陈哈哈2    | 男  | 18班  | 9年级2   |
|      7 | 扈亚鹏2    | 男  | 18班  | 9年级2   |
|      8 | 徐立楠2    | 女  | 18班  | 9年级2   |
|      9 | 陈子凝2    | 女  | 18班  | 9年级2   |
|     10 | 刘晓莉2    | 女  | 18班  | 9年级1   |
+--------+------------+-----+-------+----------+
10 rows in set (0.00 sec)

好了,本篇文章就到这里,希望能在你需要的时候帮助到你。

一张令人心酸的图片(一)
 

这是我一个喜欢上网的朋友拍到的。
干完活的父亲,在网吧呆到没去上学的儿子。

曾经的我也是电脑前的顽童
年少不知父母恩,半生糊涂半生人。

猜你喜欢

转载自blog.csdn.net/qq_39390545/article/details/107730776