2

我想为 SQLquery 进行参数化查询,可以是这样的:

SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN (1, 2, 3));

这些值来自 WS 接口,虽然我可以信任消费者,但我想安全地使用它并使用涉及 DbParameters 的参数化查询来防止 SQL 注入。怎么做?

谢谢!

4

3 回答 3

3

正如您所注意到的,关键点是使用参数。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 值”的情况。

于 2013-03-08T13:55:01.430 回答
1

这是一个例子:

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

于 2013-03-08T13:50:24.630 回答
1

这里的困难是参数化每个单独的 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));
于 2013-03-08T13:53:40.213 回答