使用.NET C#操作数据库报错:关键字'User'附近语法不正确
问题描述
我编写了一段.NET C#代码用于SQL Server数据库操作,实现用户名存在性校验及新账户插入功能,代码如下:
try { //insert data into database //check if data already exists using (SqlConnection con = new SqlConnection(@"Server=DESKTOP-31579CJ\SQLEXPRESS;Database=LoginInformation;Trusted_connection = True;")) { SqlCommand cmd = new SqlCommand(@"SELECT User.Username FROM User WHERE Username = '" + Username.Text + "'", con); con.Open(); SqlDataReader dr = cmd.ExecuteReader(); if (dr.Read()) { MessageBox.Show("Username already exists"); } else { MessageBox.Show("Account created"); cmd = new SqlCommand(@"INSERT INTO User (Username,Password) VALUES ('" + Username.Text + "','" + Password.Password + "')", con); cmd.ExecuteNonQuery(); //clear textboxes Username.Text = ""; Password.Password = ""; } dr.Close(); con.Close(); } } catch (Exception ex) { MessageBox.Show("Exception occured" + ": " + ex.Message); SqlConnection con = new SqlConnection(@"Data Source=DESKTOP-31579CJ\SQLEXPRESS;Initial Catalog=LoginInformation;Integrated Security=True;User ID = yes; Password = yes"); //create table if one does not exist SqlCommand cmd = new SqlCommand("CREATE TABLE User (Username varchar(50), Password varchar(50))", con); }
执行代码时抛出异常:
Incorrect syntax near the keyword 'User'
由于很少使用C#和SQL,无法定位问题所在,希望能得到问题排查及代码优化的相关反馈。
问题排查与优化方案
1. 核心异常原因:SQL保留关键字冲突
User是SQL Server的保留关键字,直接用作表名会导致语法解析错误。解决方法是用方括号[User]包裹表名,让SQL引擎将其识别为普通表名。
2. 紧急修复:消除SQL注入风险
原代码使用字符串拼接生成SQL语句,这是极其危险的做法,攻击者可以通过输入恶意字符串篡改SQL逻辑(比如输入' OR 1=1 --直接绕过校验甚至篡改数据)。必须改用参数化查询:
- 使用
SqlCommand.Parameters.Add方法传递参数,避免字符串拼接 - 参数化查询还能自动处理特殊字符转义,避免语法错误
3. 代码逻辑与资源管理优化
- 连接自动释放:
using块会自动调用SqlConnection.Dispose(),无需手动调用con.Close() - DataReader资源管理:将
SqlDataReader也放入using块,自动释放资源,避免内存泄漏 - 异常处理修正:原catch块中创建表的逻辑存在问题——未打开连接就执行命令,且连接字符串重复;创建表的逻辑应该在程序初始化时执行,而非异常触发时
- 密码存储安全:明文存储密码是严重安全漏洞,必须使用哈希算法(如SHA256、BCrypt)对密码进行哈希后存储
优化后的完整代码
using System.Data.SqlClient; using System.Security.Cryptography; using System.Text; // 建议将连接字符串放在配置文件中,而非硬编码 private const string ConnectionString = @"Server=DESKTOP-31579CJ\SQLEXPRESS;Database=LoginInformation;Trusted_Connection=True;"; private void CreateUserTableIfNotExists() { // 初始化时创建表(仅执行一次) using (SqlConnection con = new SqlConnection(ConnectionString)) { string createTableSql = @"IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'User') CREATE TABLE [User] (Username varchar(50) PRIMARY KEY, PasswordHash varchar(64))"; using (SqlCommand cmd = new SqlCommand(createTableSql, con)) { con.Open(); cmd.ExecuteNonQuery(); } } } private bool IsUsernameExists(string username) { using (SqlConnection con = new SqlConnection(ConnectionString)) { string checkSql = @"SELECT 1 FROM [User] WHERE Username = @Username"; using (SqlCommand cmd = new SqlCommand(checkSql, con)) { cmd.Parameters.AddWithValue("@Username", username); con.Open(); return cmd.ExecuteScalar() != null; } } } private string HashPassword(string password) { // 使用SHA256哈希密码(生产环境推荐使用BCrypt等带盐的哈希算法) using (SHA256 sha256 = SHA256.Create()) { byte[] bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password)); StringBuilder builder = new StringBuilder(); foreach (byte b in bytes) { builder.Append(b.ToString("x2")); } return builder.ToString(); } } private void CreateAccount() { // 先确保表存在 CreateUserTableIfNotExists(); string username = Username.Text.Trim(); string password = Password.Password; if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) { MessageBox.Show("请输入用户名和密码"); return; } if (IsUsernameExists(username)) { MessageBox.Show("用户名已存在"); return; } try { string passwordHash = HashPassword(password); using (SqlConnection con = new SqlConnection(ConnectionString)) { string insertSql = @"INSERT INTO [User] (Username, PasswordHash) VALUES (@Username, @PasswordHash)"; using (SqlCommand cmd = new SqlCommand(insertSql, con)) { cmd.Parameters.AddWithValue("@Username", username); cmd.Parameters.AddWithValue("@PasswordHash", passwordHash); con.Open(); cmd.ExecuteNonQuery(); } } MessageBox.Show("账户创建成功"); // 清空输入框 Username.Text = ""; Password.Password = ""; } catch (Exception ex) { MessageBox.Show($"创建失败:{ex.Message}"); } }
额外说明
- 连接字符串管理:建议将连接字符串放入
app.config或appsettings.json中,便于维护和修改 - 哈希算法选择:SHA256是单向哈希,但仍推荐使用带随机盐的算法(如BCrypt、Argon2),防止彩虹表攻击
- 输入验证:增加了用户名和密码的非空校验,避免无效数据插入
内容的提问来源于stack exchange,提问作者bobv1st
相关产品推荐
相关产品推荐

