直接拼接SQL字符串易导致SQL注入,因用户输入如' OR 1=1 -- 可绕过校验;参数化查询通过分离结构与数据杜绝该风险。

为什么直接拼接 SQL 字符串会出问题
因为 string.Format 或 + 拼出来的 SQL,参数值会直接嵌入语句文本里,数据库不区分“代码”和“数据”。用户输入 ' OR 1=1 -- 就能绕过登录校验,这是典型的 SQL 注入。参数化查询把值和结构分开,让数据库引擎严格按类型、长度解析参数,从根本上堵住这个口子。
SqlCommand.Parameters.Add() 的三种常用写法及推荐选择
新手常卡在怎么加参数——Add()、AddWithValue()、带类型重载的 Add() 行为差异很大:
-
AddWithValue("@name", "Alice"):方便但危险。SQL Server 会根据 .NET 类型推断 SQL 类型(比如把string推成nvarchar(1)),导致索引失效或隐式转换失败 -
Add("@name", SqlDbType.NVarChar).Value = "Alice":明确指定类型和长度,性能稳定,推荐用于关键查询 -
Add(new SqlParameter("@name", SqlDbType.NVarChar, 50) { Value = "Alice" }):适合需要复用参数对象或设置更多属性(如IsNullable)的场景
参数名大小写与命名规范的实际影响
SQL Server 对参数名不区分大小写,但 SqlCommand 解析时要求参数名必须和 SQL 中完全一致(包括大小写)。如果 SQL 写的是 WHERE id = @ID,而代码用 Parameters.Add("@id", ...),运行时抛出 System.InvalidOperationException: The parameterized query '...' expects parameter '@ID', which was not supplied.。
建议统一用小写加下划线(如 @user_id)或 PascalCase(如 @UserId),并在整个项目中保持一致。避免混用 @UserId 和 @userid。
NULL 值传参必须用 DBNull.Value,不能用 null
C# 的 null 和数据库的 NULL 是两回事。如果参数可能为空,别写 Parameters.Add("@email", email) —— 当 email == null 时,AddWithValue 会传入 DBNull.Value(侥幸能过),但显式类型添加会直接报错。
安全写法是显式判断:
cmd.Parameters.Add("@email", SqlDbType.VarChar, 255).Value =
string.IsNullOrEmpty(email) ? DBNull.Value : (object)email;
注意必须转成 object,否则编译不过;也别漏掉 DBNull.Value 的 DB 大写。
最常被忽略的其实是参数顺序无关性——SQL Server 按参数名匹配,不是按 Add 的顺序。但有些旧版 ODBC 驱动或特定 ORM 封装仍依赖顺序,所以即使用了参数化,也别随意打乱 SQL 中的参数出现顺序和代码中的 Add 顺序,除非你确认底层驱动支持纯名称绑定。


















