显然,以下代码不会按预期打印任何内容。我确信这与我尝试将项目列表放入@namelist
的事实有关。显然,它不仅仅是文本替代品。
我该如何解决这个问题?谢谢
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = @"select column_name, table_name from information_schema.columns where table_name in (@namelist)";
cmd.Parameters.AddWithValue("@namelist", "'tableOne', 'tableTwo'");
var reader = cmd.ExecuteReader();
while (reader.Read())
{
var a = reader[0];
Console.WriteLine(a);
}
}
}
答案 0 :(得分:7)
不幸的是,SQL参数不会以这种方式解析,换句话说,后端不只是构建一个安全字符串,用其值替换每个参数。相反,您必须动态构建参数列表:
cmd.CommandText = @"select column_name, table_name from information_schema.columns where table_name in (@p1, @p2, @p3)"; // This can be built dynamically
然后添加每个参数:
cmd.Parameters.AddWithValue("@p1", "tableOne");
cmd.Parameters.AddWithValue("@p2", "tableTwo");
cmd.Parameters.AddWithValue("@p3", "tableThree");
如果在运行时之前数字未知,您当然可以在循环中添加这些参数:
for(var i = 0; i < myParams.length; i++)
{
cmd.Parameters.AddWithValue("@p" + i.ToString(), myParams[i]);
}
如果您的表列表存储在enum
中,或者您可以将它们转义或使用正则表达式验证它们,那么自己构建原始SQL并且根本不使用参数也是相当安全的
这当然是我使用PostgreSQL的一个重要原因;对数组的本机支持。
答案 1 :(得分:4)
正如已经指出的那样,“in”列表等在ado.net中是出了名的尴尬;因此,一些工具提供了方便的帮助方法。 例如,Dapper 在“in”语法中提供了一个变体,它会自动扩展为正确的参数化形式(仍然保留注入安全性等) - 在类型绑定和“动态”使用中。例如:
string[] namelist = ...
foreach(var row in conn.Query(@"
select column_name, table_name
from information_schema.columns
where table_name in @namelist",
new { namelist } ))
{
string col = row.column_name,
table = row.table_name;
// ..
}
这也避免了使用db-command / parameter / reader的麻烦。请注意“in” 没有 括号,用于识别此模式。
答案 2 :(得分:-2)
您目前没有使用您的列表。如果您不需要其它东西,您可以简单地执行此操作:
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = @"select column_name, table_name from information_schema.columns where table_name in ('tradeName', 'tableOne', 'tableTwo')"
var reader = cmd.ExecuteReader();
while (reader.Read())
{
var a = reader[0];
Console.WriteLine(a);
}
}
这将检查它是否在这3个值中。