我想为 SQLquery 进行参数化查询,可以是这样的:
SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN (1, 2, 3));
这些值来自 WS 接口,虽然我可以信任消费者,但我想安全地使用它并使用涉及 DbParameters 的参数化查询来防止 SQL 注入。怎么做?
谢谢!
我想为 SQLquery 进行参数化查询,可以是这样的:
SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN (1, 2, 3));
这些值来自 WS 接口,虽然我可以信任消费者,但我想安全地使用它并使用涉及 DbParameters 的参数化查询来防止 SQL 注入。怎么做?
谢谢!
正如您所注意到的,关键点是使用参数。IN
条款是出了名的问题,烦人。现在,如果您知道这些值都是整数(例如,您正在int[]
为您的 C# 方法提供一个参数),那么您几乎可以摆脱以下情况:
cmd.CommandText = "SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN ("
+ string.Join(",", values) + "))"; // please don't!!!
这太可怕了,暗示了一种非常糟糕的做法(如果有人将它复制为字符串,那么您将陷入痛苦的世界),并且不能使用查询计划缓存。您可以执行以下操作:
var sb = new StringBuilder("SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN (");
int idx = 0;
foreach(var val in values) {
if(idx != 0) sb.Append(',');
sb.Append("@p").Append(idx);
cmd.Parameters.AddWithValue("@p" + idx, val);
idx++
}
sb.Append("))");
cmd.CommandText = sb.ToString();
哪个更可取但很尴尬。
或者最简单:使用像dapper这样的工具,让库担心它:
var data = conn.Query<YourType>(
"SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN @values)",
new { values });
在这里, dapper发现了用法并“做正确的事”。它还为您处理“0 值”的情况。
这是一个例子:
SqlCommand cmd = new SqlCommand("SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 = @myparam", conn);
//define parameters used in command object
SqlParameter param = new SqlParameter();
param.ParameterName = "@myparam";
param.Value = "myvalue";
//add new parameter to command object
cmd.Parameters.Add(param);
// get data stream
reader = cmd.ExecuteReader();
查看此链接了解更多详情: http ://csharp-station.com/Tutorial/AdoDotNet/Lesson06
这里的困难是参数化每个单独的 IN 子句,以便您可以传递可变数量的 ID。
查看这篇有用的文章,了解解决此问题的一种方法:http: //www.mikesdotnetting.com/Article/116/Parameterized-IN-clauses-with-ADO.NET-and-LINQ
基本上,它涉及一些字符串操作来构建 IN 子句的参数化列表,因此对于具有 3 个 ID 的特定示例,您最终会得到一个如下所示的 SQL 语句:
select * from TABLE1 where COL1 in (select COL2 from TABLE2 where COL3 IN (@p1, @p2, @p3));