c# - 在 C# SQL 查询中,Parameters.Add() 比直接在查询中嵌入值有什么优势?

标签 c# sql .net

最近,我看到很多人使用 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()(如第一个代码示例)而不是将该值嵌入查询字符串(如第二个代码示例)的优势是什么例如)?

编辑添加:

一些评论引用了我将变量 onetwo 声明为硬编码的事实。我这样做是为了让示例完整 - 自然地,变量将来自其他地方。

最佳答案

使用参数要好得多!

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

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

防止注入(inject)是另一个优势。如果您将查询文本构造为

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

然后 someone谁将他们的名字输入为“罗伯特”;DROP TABLE [Students]”可以破坏您的数据库。但是,如果您使用参数化的固定查询文本并添加相同的名称作为参数,

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

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

关于c# - 在 C# SQL 查询中,Parameters.Add() 比直接在查询中嵌入值有什么优势?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50109216/

相关文章:

javascript - Web SQL 向多行插入数据

asp.net - 本地主机上的 SQL Server 2008 : Connection continually refused

.net - OrderBy、GetNewBindingList 和 Linq to SQL

c# - 如何检查目录或其任何子目录中是否存在特定文件

c# - 使用 DI 和 InstanceContextMode.Percall 的自定义 ServiceHost

Java 相当于 NetworkCredential

sql - 如何从SQL Server发送邮件?

表上的 SQLite 多主键,其中之一是自动增量

c# - Process.从用户机器开始

c# - 从对象列表到具有两个属性的字典的优雅方式