MySQL选择语句,表名从数据库查询派生

64jmpszr  于 2023-01-04  发布在  Mysql
关注(0)|答案(2)|浏览(88)

我想写一个SELECT语句,其中的表名基于对另一个SELECT查询的响应,我不能使用堆栈查询,只能使用MySQL。
作为伪代码,我想做的是:

tablenamevariable = (SELECT 'tablename');
SELECT * FROM tablenamevariable;

这应该等效于执行SELECT * FROM tablename(其中字符串tablename来自数据库)。
到目前为止,我已经成功执行了以下代码:

SELECT * FROM (SELECT 'tablename') AS x;

但是,结果只是打印tablename(这不是我想要的)。
后台是一个SQL注入,所有输入都是大写的,所以我想做的是SELECT * FROM (SELECT CHAR([...] USING UTF8MB4)),以便能够从名称中有小写字符的表中选择数据。

ws51t4hk

ws51t4hk1#

不能在同一查询中将字符串用作标识符。
子查询或表达式可以返回字符串,但不能返回标识符。
因此,像select ... from (select ...) as x这样的子查询并不像您想象的那样工作,它不会从字符串命名的表中查询,而是从由子查询返回的字符串值组成的派生表中查询。

mysql> select * from (select 'abc' as tablename) as x;
+-----------+
| tablename |
+-----------+
| abc       |
+-----------+

这是因为在SQL中,所有标识符必须在分析查询时、在计算任何表达式之前固定下来。这样才能验证表名是否存在相应的表,并且您具有读取这些表的SQL权限。
另一个原因是,如果子查询按您期望的方式工作,那么就没有办法简单地从子查询查询字符串,而 * 不 * 查询由这些字符串命名的假设表。另外,如果子查询返回多列或多行,您期望它做什么?
您在一次编辑中澄清了,您尝试做的是在使用大写表名格式化查询后查询表,而不管表是如何定义的。
MySQL中标识符的大小写敏感性有点复杂,因为MySQL在不同的操作系统上有不同的版本,有些版本的文件系统区分大小写,有些版本的文件系统不区分大小写。
但结果是,在大多数情况下,表名在查询中是否大写并不重要,在使用不区分大小写文件系统的操作系统上,表名比较默认不区分大小写。

mysql> select * from mytable limit 1;
+----+-------+
| pk | name  |
+----+-------+
|  3 | hello |
+----+-------+

mysql> select * from MYTABLE limit 1;
+----+-------+
| pk | name  |
+----+-------+
|  3 | hello |
+----+-------+

mysql> select * from MyTable limit 1;
+----+-------+
| pk | name  |
+----+-------+
|  3 | hello |
+----+-------+

(Test在MacOS上的MySQL 8.0.31上执行)
在UNIX和Linux上,默认情况下表比较是区分大小写的。但是,如果您希望它在UNIX或Linux上以不区分大小写的方式工作,则可以使用一个选项进行配置。您应该阅读https://dev.mysql.com/doc/refman/8.0/en/identifier-case-sensitivity.html以了解它在不同操作系统上的工作方式,以及可以用来控制它的选项。

llmtgqce

llmtgqce2#

为此,您需要使用预准备语句:

set @t = 'tablename';
PREPARE stmt FROM concat('select * from ', @n);
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

这是非常不寻常的,你会需要这样做虽然。

相关问题