我正在尝试实现具有以下签名的 API:
public static List<string> SearchDatabase(
string column,
string value);
API 的实现需要构造一个带有 WHERE
子句的 SQL SELECT
查询,该子句使用在 column
参数中指定的列名.
查询:
string query =
string.Format(
"SELECT Name, @Column " +
"FROM Db1 " +
"INNER JOIN Db2 ON Db1.Id = Db2.Id " +
"WHERE @Column = @Value");
SQL命令及参数:
SqlCommand selectCmd =
new SqlCommand(
query,
connection);
selectCmd.CommandTimeout = SqlCommandTimeout;
selectCmd.Parameters.AddRange(
new SqlParameter[]
{
new SqlParameter("@Column", column),
new SqlParameter("@Value", value)
});
然后我这样执行:
SqlDataReader sqlDataReader = selectCmd.ExecuteReader();
while (sqlDataReader.Read())
{
// ...
}
问题是 sqlDataReader
没有返回任何行,所以我没有进入上面的 while
循环。
但是,如果我将上面查询的最后一行更改为:
"WHERE @Column = @Value");
到
"WHERE Vendor = @Value");
(即,将列名称硬编码为“供应商”)然后它就可以工作了。
我从所做的研究中了解到,不可能将列名作为参数传递,而只能传递我们查询的值。但是,它似乎确实让我在 SELECT
子句中使用了 @Column
参数,而不是 WHERE
子句。
由于 SQL 注入(inject)问题,我不想求助于动态 SQL。还有其他解决方法吗?
最佳答案
不幸的是表名,列名不能参数化。因为你知道表的结构,你可以在这个参数中有一个可能的列名的白名单,然后使用字符串连接来避免 SQL 注入(inject):
"WHERE " + Sanitize(column) + " = @Value");
关于c# - 是否可以在不求助于动态 SQL 的情况下查询用户指定的列名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7441344/