下面的代码使用预先准备好的语句来选择 home_address
在table上 students
:
SET @mycolumn = 'home_address' ;
SET @s = 'SELECT ? FROM students' ;
PREPARE statement FROM @s;
EXECUTE statement USING @mycolumn ;
实际上,这些指令只会返回一个名为“?”的列,其中填充了字符串“home\u address”,并包含与表一样多的行 students
.
我该怎么做?我知道这种语法是可能的,因为下面的示例(取自mysql中是否可以执行字符串?)
SET @username = 'test';
SET @password = 'asdf';
SET @Expression = 'SELECT id FROM Users WHERE name = ? AND pass = ?;' ;
PREPARE myquery FROM @Expression;
EXECUTE myquery USING @username, @password;
2条答案
按热度按时间dw1jzc5e1#
为了扩展jnevil所说的内容,您可以从中选择所有可能的列,而不是基于原始post中的示例动态地构建sql查询
[student]
并让应用层只返回您想要的一列。尽管这意味着在后端和前端之间传输更多的数据,但它将更加安全。例如,如果您在c#.net中进行构建(它可以是任何语言/平台-仅以此为例来说明我的意思):这样,应用程序层就可以处理一些数据管理。
oiopk7p52#
这是不可能的。不同之处在于,您动态地引用数据库的对象,而不是仅仅传入一个字符串。
prepared语句的工作方式是使用占位符完整地指定sql语句,占位符用于传递的字符串/值。然后,在传入参数之前,rdbms可以解析查询并确定它的完整执行路径。一旦该步骤完成,它将接收参数并获取数据。这就是为什么准备好的声明是如此安全。执行路径是预先确定的,因此不可能传入更多的sql并对其进行更改。
因此,如果您不知道列或表,那么它就无法解析和构建执行路径。相反,您必须使用连接和执行动态地构建sql。如果您是从用户输入中获取列名或表名,那么您必须尽可能地对其进行清理,并祈祷您的清理工作比您的偷偷摸摸的用户能够更好地注入sql。