含加密的MySQL存储过程调用异常及插入值为空问题排查
问题排查:存储过程调用参数不匹配及插入值为Null的问题
错误提示:预期0个参数但传入了6个,数据库插入的所有值均为null
原代码展示
存储过程代码
DELIMITER // CREATE Procedure customer_reg() BEGIN INSERT INTO tblcustomers (customerName, contactNo, Email, Address, Password, DoB) VALUES (AES_ENCRYPT(@customerName,'name'), AES_ENCRYPT(@contactNo, 'con'), AES_ENCRYPT(@Email,' email'), AES_ENCRYPT(@Address, 'add'), AES_ENCRYPT(@Password, 'pass'), AES_ENCRYPT(@DoB,'dob')); END // DELIMITER ;
C#调用代码
if (MessageBox.Show("Register as a customer?", "CONFIRM", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { try { con.Open(); MySqlCommand cmd = new MySqlCommand("customer_reg", con); cmd.CommandType = CommandType.StoredProcedure; // Add parameters to the command cmd.Parameters.AddWithValue("@customerName", txtName.Text); cmd.Parameters.AddWithValue("@contactNo", txtPhone.Text); cmd.Parameters.AddWithValue("@Email", txtEmail.Text); cmd.Parameters.AddWithValue("@Address", txtAddress.Text); cmd.Parameters.AddWithValue("@Password", txtPassword.Text); cmd.Parameters.AddWithValue("@DoB", dtpDOB.Value); // Execute the command int rowsAffected = cmd.ExecuteNonQuery(); if (rowsAffected > 0) { // Retrieve the last inserted ID cmd.CommandText = "SELECT 1160068"; int id = Convert.ToInt32(cmd.ExecuteScalar()); // Display a message MessageBox.Show("Registered Successfully. Customer ID: " + id.ToString(), "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); // Clear the data ClearData(); } else { MessageBox.Show("Registration failed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { con.Close(); } } else { ClearData(); }
问题根源及解决方法
1. 存储过程未声明输入参数
原存储过程customer_reg()未定义任何输入参数,代码中的@customerName等是未赋值的MySQL会话变量(默认Null),而非存储过程参数。当C#端传入6个参数时,数据库会认为存储过程不需要参数,直接抛出"预期0个参数但传入了6个"的错误。
修正后的存储过程:
DELIMITER // CREATE Procedure customer_reg( IN p_customerName VARCHAR(255), IN p_contactNo VARCHAR(20), IN p_Email VARCHAR(255), IN p_Address TEXT, IN p_Password VARCHAR(255), IN p_DoB DATE ) BEGIN INSERT INTO tblcustomers (customerName, contactNo, Email, Address, Password, DoB) VALUES (AES_ENCRYPT(p_customerName,'name'), AES_ENCRYPT(p_contactNo, 'con'), AES_ENCRYPT(p_Email,'email'), -- 去掉原密钥中的空格,避免加密不一致 AES_ENCRYPT(p_Address, 'add'), AES_ENCRYPT(p_Password, 'pass'), AES_ENCRYPT(p_DoB,'dob')); END // DELIMITER ;
2. C#端参数名需匹配存储过程定义
修改C#代码中的参数名,与存储过程声明的参数名保持一致:
// 替换原参数添加代码 cmd.Parameters.AddWithValue("@p_customerName", txtName.Text); cmd.Parameters.AddWithValue("@p_contactNo", txtPhone.Text); cmd.Parameters.AddWithValue("@p_Email", txtEmail.Text); cmd.Parameters.AddWithValue("@p_Address", txtAddress.Text); cmd.Parameters.AddWithValue("@p_Password", txtPassword.Text); cmd.Parameters.AddWithValue("@p_DoB", dtpDOB.Value);
3. 插入值为Null的解决
原存储过程使用未赋值的会话变量@customerName等,导致加密后的值为Null。修正后使用传入的存储过程参数,即可正确获取前端传入的值并加密插入。
额外优化建议
- 避免使用
AddWithValue,推荐明确指定参数类型和长度,避免潜在的类型转换问题:cmd.Parameters.Add("@p_customerName", MySqlDbType.VarChar, 255).Value = txtName.Text; - 获取最后插入ID的代码改为
SELECT 877171;,替代固定值1160068,确保拿到实际插入的客户ID。
内容的提问来源于stack exchange,提问作者SanMiguelWatch
相关产品推荐
相关产品推荐

