有没有一种方法可以使用一个准备好的语句来选择一个变量列?

w8rqjzmb  于 2021-06-25  发布在  Mysql
关注(0)|答案(2)|浏览(351)

下面的代码使用预先准备好的语句来选择 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;
dw1jzc5e

dw1jzc5e1#

为了扩展jnevil所说的内容,您可以从中选择所有可能的列,而不是基于原始post中的示例动态地构建sql查询 [student] 并让应用层只返回您想要的一列。尽管这意味着在后端和前端之间传输更多的数据,但它将更加安全。例如,如果您在c#.net中进行构建(它可以是任何语言/平台-仅以此为例来说明我的意思):

DataTable dataTable = new DataTable();
string columnName = "home_address";

string connString = @"your connection string here";
string query = "SELECT home_address, work_address, name /*... any other columns the user may want*/ FROM students";

//Alternatively, you can use the following, but it leaves you exposed to SQL injections, even after sanitizing:
//string query = $"SELECT [{columnName}] FROM students";

SqlConnection conn = new SqlConnection(connString);        
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();

SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dataTable);
conn.Close();
da.Dispose();

List<object> list = new List<object>();
foreach (DataRow row in dataTable.Rows)
{
    list.Add(row[columnName]);
}

这样,应用程序层就可以处理一些数据管理。

oiopk7p5

oiopk7p52#

这是不可能的。不同之处在于,您动态地引用数据库的对象,而不是仅仅传入一个字符串。
prepared语句的工作方式是使用占位符完整地指定sql语句,占位符用于传递的字符串/值。然后,在传入参数之前,rdbms可以解析查询并确定它的完整执行路径。一旦该步骤完成,它将接收参数并获取数据。这就是为什么准备好的声明是如此安全。执行路径是预先确定的,因此不可能传入更多的sql并对其进行更改。
因此,如果您不知道列或表,那么它就无法解析和构建执行路径。相反,您必须使用连接和执行动态地构建sql。如果您是从用户输入中获取列名或表名,那么您必须尽可能地对其进行清理,并祈祷您的清理工作比您的偷偷摸摸的用户能够更好地注入sql。

相关问题