C#注册功能报System.Data.SqlClient.SqlException主键约束冲突问题
报错核心成因
Violation of PRIMARY KEY constraint报错的本质是向设置了主键约束的表中插入了已存在的主键值,结合你的代码具体触发原因有3个核心bug:
- 用户名重名校验逻辑完全失效:你写的重名校验SQL中,拼接的是
tbRegisterUser控件对象本身,不是用户输入的tbRegisterUser.Text属性值,字符串拼接时会自动调用控件的ToString方法,得到的是System.Windows.Forms.TextBox固定值,导致无论用户输入什么用户名,校验逻辑都会判定为用户名不存在,直接执行插入操作,自然会因为重复插入已存在的用户名(主键)触发报错。 - INSERT语句写法不规范:你写的
insert into tbl_acc values (@username, @password)省略了字段名,会强制要求values值的顺序和表定义的字段顺序完全一致。如果你的表第一个字段是自增主键ID,这行代码会把用户名赋值给ID主键字段,必然会触发主键冲突。 - 非空校验逻辑错误:你的非空校验用了
||逻辑或,只要任意一个字段不为空就进入后续逻辑,不符合「三个字段都要填写」的要求,会出现字段为空的插入请求,也可能触发主键冲突。
修复方案
按以下步骤修改即可解决问题,同时优化代码安全性:
- 修正重名校验逻辑,改用参数化查询(同时避免SQL注入风险)
- INSERT语句显式指定插入字段,避免字段顺序错位
- 修正非空校验的逻辑判断符
- 用using语句自动释放数据库相关资源,避免内存泄漏
修复后完整代码
private void btnRegister_Click(object sender, EventArgs e) { // 非空校验,逻辑或改逻辑与,增加Trim处理前后空格 if (tbRegisterConfirmPassword.Text.Trim() != string.Empty && tbRegisterPassword.Text.Trim() != string.Empty && tbRegisterUser.Text.Trim() != string.Empty) { if (tbRegisterPassword.Text.Trim() == tbRegisterConfirmPassword.Text.Trim()) { // using自动释放连接,不用手动Close using (SqlConnection con = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;Initial Catalog=LoginInfo;Persist Security Info=True;User ID=MJ;Password=12345")) { con.Open(); // 参数化查询校验用户名是否存在 using (SqlCommand checkCmd = new SqlCommand("select 1 from tbl_acc where username = @username", con)) { checkCmd.Parameters.AddWithValue("@username", tbRegisterUser.Text.Trim()); using (SqlDataReader dr = checkCmd.ExecuteReader()) { if (dr.Read()) { lbRegister.Text = "Username Already Taken"; lbRegister.ForeColor = Color.Red; return; } } } // 显式指定字段插入,避免和表字段顺序不匹配的问题 using (SqlCommand insertCmd = new SqlCommand("insert into tbl_acc (username, password) values (@username, @password)", con)) { insertCmd.Parameters.AddWithValue("@username", tbRegisterUser.Text.Trim()); insertCmd.Parameters.AddWithValue("@password", tbRegisterPassword.Text.Trim()); insertCmd.ExecuteNonQuery(); } MessageBox.Show("Your account has now been registered", "Registration Success", MessageBoxButtons.OK, MessageBoxIcon.Information); } } else { lbRegister.Text = "Password does not match"; lbRegister.ForeColor = Color.Red; } } else { lbRegister.Text = "Please fill out all the fields"; lbRegister.ForeColor = Color.Red; } }
内容的提问来源于stack exchange,提问作者gr een
相关产品推荐
相关产品推荐

