包含IN 参数的SqlCommand问题

显然,以下代码不会按预期打印任何内容。我确信这是因为我试图将项目列表放入@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); } } } 

不幸的是,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 ,或者您可以使用正则表达式对它们进行转义或validation它们,那么自己构建原始SQL并且根本不使用参数也是相当安全的。

当然,这是我使用PostgreSQL的一个重要原因; 对数组的本机支持。

正如已经指出的那样,“in”列表等在ado.net中是出了名的尴尬; 因此,一些工具提供了方便的帮助方法。 例如,Dapper在“in”语法中提供了一个变体,它自动扩展为正确的参数化forms(仍保留注入安全性等) – 在类型绑定和“动态”使用中。 例如:

 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” 没有用于识别此模式的括号。

您现在没有使用您的列表。 如果您不需要其他东西,您可以简单地执行此操作:

  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个值中。