首页 > 解决方案 > 在 C# SQL 查询中,与直接在查询中嵌入值相比,Parameters.Add() 有什么优势?

问题描述

最近,我看到很多人使用 SQLCommand 的 Parameters 属性为查询提供简单的值 - 像这样:

var one = "one";
var two = "two";

DataTable results = new DataTable();
string cmdTxt = String.Format("select NAME from TABLE where NAME like @ONE or NAME like @TWO");
using (SqlCommand cmd = new SqlCommand(cmdTxt, Butch.connection))
{
    cmd.Parameters.Add("@ONE", SqlDbType.Char, 15).Value = "%" + one + "%";
    cmd.Parameters.Add("@TWO", SqlDbType.Char, 65).Value = "%" + two + "%";
    using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
           adapter.Fill(results);
 }

从历史上看,我刚刚将值嵌入到查询字符串中,如下所示:

var one = "one";
var two = "two";

DataTable results = new DataTable();
string cmdTxt = String.Format($"select NAME from TABLE where NAME like '%{one}%' or NAME like '%{two}%");
using (SqlCommand cmd = new SqlCommand(cmdTxt, Butch.connection))
{
    using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
           adapter.Fill(results);
}

我知道有些情况cmd.Parameters.Add()特别有用(比如插入二进制数据),所以我不问这些。

我特意问:

对于一个简单的值,使用cmd.Parameters.Add()(如在第一个代码示例中)而不是将该值嵌入到查询字符串中(如在第二个示例中)有什么优势?

编辑添加:

一些评论提到了我声明变量one并且two是硬编码的事实。我这样做是为了使示例完整——自然,变量将来自其他地方。

标签: c#sql.net

解决方案


使用参数要好得多!

为了处理查询,SQL 经历了几个步骤。首先,它解析查询文本以检查其语法并创建AST表示。然后它将 AST 提供给查询计划器以生成将用于执行查询的计划。然后它执行计划并返回结果。

如果你再次给它相同的查询文本,它会识别并跳过解析和规划步骤,只是重新执行计划。对于许多查询,解析和规划比计划执行花费的时间要长得多,因此可以带来巨大的性能提升。当查询被参数化时,计划本身接受参数,因此可以重复使用。当值在查询文本中逐字出现时,每次值更改时都需要重新解析和重新规划文本。

防止注射是另一个优点。如果将查询文本构造为

command.CommandText = $"SELECT * FROM [Students] WHERE [Name] = '{name}'";

那么输入名字为“Robert'; DROP TABLE [Students]”的人可以摧毁你的数据库但是,如果您使用参数化的固定查询文本并添加与参数相同的名称,

command.CommandText = "SELECT * FROM [Students] WHERE [Name] = @name";
...
command.Paramers.Add("@name",name);

然后数据库将完成在数据库中查找该名称的工作,而不会破坏它。


推荐阅读