为什么字符串.格式工作,但SqlCommand.Parameters.Add不
本文关键字:SqlCommand Parameters Add 字符串 格式 工作 为什么 | 更新日期: 2023-09-27 18:17:49
我有一个Project
表,其中有两列——ProjectId
和ProjectName
——并且正在编写一个函数,该函数构建并执行SqlCommand
以查询数据库中具有给定名称的项目的id。此命令有效,但容易受到SQL注入的攻击:
string sqlCommand = String.Format("SELECT {0} FROM {1} WHERE {2} = {3}",
attributeParam, tableParam, idParam, surroundWithSingleQuotes(idValue));
SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable attributes = new DataTable();
adapter.Fill(attributes);
...
}
attributeParam
、tableParam
、idParam
、idValue
均为字符串。例如,可能分别为"ProjectId"
、"Project"
、"ProjectName"
和"MyFirstProject"
。surroundWithSingleQuotes
用''
包围字符串,即surroundWithSingleQuotes(idValue) == "'MyFirstProject'"
。我试图写这个函数尽可能通用,因为我可能想从表中获得所有的给定属性在未来。
虽然上面的字符串。格式工作,这不是:
string sqlCommand = String.Format("SELECT @attributeparam FROM {0} WHERE " +
"@idparam = @idvalue", tableParam);
command.Parameters.Add(new SqlParameter("@attributeparam", attributeParam));
command.Parameters.Add(new SqlParameter("@idparam", idParam));
command.Parameters.Add(new SqlParameter("@idvalue",
surroundWithSingleQuotes(idValue)));
SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable attributes = new DataTable();
adapter.Fill(attributes);
...
}
我不知道为什么。我没有得到错误消息,但是当我使用SqlDataAdapter
填充我的DataTable
时,DataTable不包含任何内容。以下是我采取的各种方法,但都无济于事:
- 遵循这个答案和微软的文档,使用
AddWithValue
或使用Parameters.Add
和SqlParameter.Value
。 - 选择性地将
String.Format
中的{0}
、{1}
、{2}
、{3}
替换为实际值或参数字符串。
在我代码的其他地方,我使用了参数化查询(尽管只有一个参数),没有问题。
基本上SQL中的参数只适用于值 -而不是列或表的标识符。在您的示例中,只有最后一个参数表示一个值。
如果您需要在列名和表名方面是动态的,那么您需要自己构建这部分SQL。由于所有与SQL注入攻击相关的正常原因,请非常小心。理想情况下,只允许已知的表和列值的白名单。如果您需要更通用,我建议执行非常严格的验证,并引用标识符以避免与关键字冲突(或者理想情况下完全禁止这些)。
这是一个有效的语句:SELECT * FROM SomeTable WHERE SomeColumn=@param
而这不是:SELECT * FROM @param
这意味着你可以使用参数值,而不是表名,视图名,列名等。