这些天在做新生培训的时候查阅了大量的资料,从其中明白了很多以前迷迷糊糊的点,也get到了很多新的有意思的东西。
ps:我自己都是个菜鸡,只希望不误导萌新们就好。
利用mysql中的innodb相关表获得表名
在mysql中,存储数据的默认引擎分为两种
- 一类是在5.5.x之前的MyISAM数据村粗引擎
- 另一类是5.5.x版本后的inodb引擎。
在mysql5.5版本之后将innodb作为数据库的默认引擎
而在mysql5.6版本起,innodb增添了两个新表,一个是innodb_index_stats
,另一个是innodb_table_stats
(都是在mysql库中),两个库中都会存储数据库和对应的数据表(没有字段名)
innodb_table_stats表:
innodb_index_stats表:
两个表中都有table_name和database_name字段。
table_name为表名,database_name为数据库名
因此,我们可以利用这两个表来查询某个数据库中的所有的表名
payload:
1 | select group_concat(table_name) from mysql.innodb_index_stats where database_name=database() |
Q:但这仅仅是查到了表名,想要查数据还得知道列名啊,这可咋整?
A:谁说查数据必须得知道列名的?
通过反引号和select形成的虚拟表在不知道列名的情况下获取数据
先看看mysql中的反引号
反引号(`)在mysql中用来区分保留字
例如有表A:
id | select |
---|---|
1 | 2 |
当我们想要查询表A中的select列时,怎么办?
select select from A; ==> 错误
select `select` form A; ==> 正确
再看看select的虚拟表
当我们使用select 语句的时候,结果总是成一张表格的形式的
比如:select * from users;
结果就是以表的形式返回的。
因此,可不可以在这个表的基础上再次进行查询呢?
所以,做了以下实验:
1 | select * from (select * from users); |
结果报错,ERROR 1248 (42000): Every derived table must have its own alias
当然,我们怎么可能从一个连名字都没有的表中获得信息呢。
因此,给select 生成的虚拟表加一个别名
1 | select * from (select * from users)a; |
结果是成功查出了表中的数据
再看看如果我们仅仅是select,而不从表中查询数据,这时的虚拟表是长啥样的。
比如:select 1,2,3;
可以看到这时的结果任然是一个表,而且表的列名是由我们的查询的东西构成的。
Q:而这又能代表什么呢?我是想从一个不知道列名的表中获得数据啊。
A:别急,慢慢来~~
这里我们知道了我们可以从select建立的虚拟表中获得数据,而且如果我们仅仅是select,这时的虚拟表的列名是我们可控的。再结合上面的反引号的问题,是不是我们就可以获得一个select形成的虚拟表中的所有内容了。
而这时,只要我们在select之后再使用union联合查询,将我们想要的数据添加到这个虚拟表中,就可以获取一个表中的所有数据了
比如:select 1,2 union select * from users;
这时的表是这样的:
它包含了users表中的所有数据,但列名却是1和2
所以可以使用以下语句来查询这个表
1 | select `1`,`2` from (select 1,2 union select * from users)a; |
到这里,我们就实现了无列名查询表中数据。
payload:
1 | select group_concat(`i`) from (select 1,2,3,4,5,6 union select * from 表名)a; |
例如:
表A共有3列数据,我们想要查询表中的第一列:select group_concat(\
1) from (select 1,2,3 union select * from A)a;