在SQL命令中使用字符串插值

3

有没有更简单的方法在下面的插入SQL命令中使用namephone变量?

字符串插值是一种方法,但我不知道如何实现。

String name = textBox1.Text;
String phone = textBox2.Text;  
     
var query = "insert into Customer_info(Customer_Name,Customer_Phone) " +
            "values('" + name + "','" + phone + "');";
SqlCommand com = new SqlCommand(query,con);

try {
    con.Open();
    com.ExecuteNonQuery();
    con.Close();
}

catch (Exception Ex) {
    con.Close();
}

不要使用连接字符串或字符串插值从用户输入构建查询字符串,而应改用参数 - 参见Little Bobby Tables - Tetsuya Yamamoto
3个回答

6

你真正应该做的是使用参数化查询,这样你的查询将如下所示:

var query = "insert into Customer_info(Customer_Name,Customer_Phone)" +
"values(@name, @phone);";

然后您将使用 SQLCommand 对象将参数传递给查询:

using (var command = new SqlCommand(query, connection))
{
    command.Parameters.AddWithValue("@name", name);
    command.Parameters.AddWithValue("@phone", phone);

    command.ExecuteNonQuery();
}

这样做的原因是为了避免SQL注入的风险(这是OWASP Top 10中的一项)。请考虑一下,如果name参数包含一些SQL语句,例如包含以下内容:

'; DROP TABLE [Customer_info]; --

那么您构造的SQL语句(如果phone参数为空)将会是这个样子:

insert into Customer_info(Customer_Name,Customer_Phone) values ('';
DROP TABLE [Customer_Info];
-- ','');

如果使用该代码连接到SQL的用户具有足够的权限,则可能会导致您的 Customer_Info 表被删除。

请注意,此操作可能会造成数据丢失,请谨慎操作。


3
@GragasIncoming,不,你真的没有按照正确的方式来做... 你正在将值连接成“query”,而我是将它们作为参数传递。 这些是构造传递给SQL Server的查询的根本不同的方法。 为了那些使用这段代码的公司的客户,请花半个小时来理解为什么连接是有问题的。下面是OWASP的一个页面,其中包含一些其他例子,可能会有所帮助:https://www.owasp.org/index.php/SQL_Injection - Rob
我认为需要添加 connection.Open(); 因为出现了错误。 - user9402741

5

不要这样做!认真点,不要这样做。字符串插值不适合用于构建SQL。只需使用参数:

var query = @"
insert into Customer_info(Customer_Name,Customer_Phone)
values(@name,@phone);";
//...
cmd.Parameters.AddWithValue("name", name);
cmd.Parameters.AddWithValue("phone", phone);
cmd.ExecuteNonQuery();

您可以使用像dapper这样的库(它为您删除了所有混乱的ADO.NET代码,例如命令、参数和读取器):

conn.Execute(query, new { name, phone });

捕获异常的方法在哪里? - user9402741
1
@GragasIncoming 我要捕获什么,为什么?坦白地说,“using”比“try”/“catch”更有用 - Rob的答案显示了它的位置。 - Marc Gravell
那么你如何输出错误信息呢?例如,在catch函数中使用ex.Message; - user9402741
1
@GragasIncoming 如果你指的是问题中的 try/catch:当我回答时,它们不在问题中;另外:你的 catch 吞噬了异常;此外,在这里很少需要 Close() 连接 - 更常见的是使用 using 来管理生命周期。请注意,关于 dapper 版本:dapper 实际上会正确处理连接的生命周期 - 如果在调用 Execute 时连接未打开,它将打开、执行并关闭等(如果最初已经打开,则不会关闭)。 - Marc Gravell
1
@GragasIncoming 关于“那么你如何输出错误信息”的问题 - 我可能会在将要显示错误的代码附近捕获它;如果您的数据访问代码和UI代码混合在一起,那就不是很好的关注点分离。 - Marc Gravell

4
要使用字符串内插,您需要编写:
```{}```
var query = $"insert into Customer_info(Customer_Name,Customer_Phone) values('{name}','{phone}');";

当然,你很容易受到SQL注入的攻击,需要避免!

使用SqlCommand.Parameters集合添加参数,可以使你免于此类攻击。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接