使用C#向SQL Server插入数据时出现语法错误,求正确实现方法
问题排查与正确实现指南
嘿,我一眼就看到你代码里的问题了,咱们一步步拆解解决:
核心错误原因
你遇到的语法错误,根源在于错误的SQL语句构建方式,还有几个细节问题:
string.Format的参数顺序完全搞反了:你把productname作为第一个参数传给string.Format,这相当于用产品名称当模板去格式化其他参数,而且你根本没把格式化后的字符串赋值给command.CommandText——导致执行的SQL语句里还是{0}、{1}这些占位符,数据库根本不认识它们,直接触发语法错误。- 用字符串拼接SQL的方式本身就有致命问题:不仅会因为特殊字符(比如产品名里的单引号
O'Neil)触发语法错误,还会暴露在SQL注入攻击的风险下,这是绝对要避免的。
正确的实现方式(参数化查询)
行业标准的做法是使用参数化查询,既安全又能避免各种语法问题,下面是修改后的完整代码:
1. 优化后的InsertProduct方法
static void InsertProduct(string productname, int productstock, int productcategoryid, int productemployeeid) { // 用using包裹SqlConnection,确保连接自动释放,不用手动Close using (SqlConnection conn = new Database().connection()) { // 参数化SQL语句,用@前缀定义参数 string sql = @"INSERT INTO Products (ProductName, ProductStock, ProductCategoryID, ProductEmployeeID) VALUES (@ProductName, @ProductStock, @ProductCategoryID, @ProductEmployeeID)"; using (SqlCommand command = new SqlCommand(sql, conn)) { // 逐个添加参数,指定类型和值(匹配数据库字段类型) command.Parameters.Add("@ProductName", SqlDbType.NVarChar, 32).Value = productname; command.Parameters.Add("@ProductStock", SqlDbType.Int).Value = productstock; command.Parameters.Add("@ProductCategoryID", SqlDbType.Int).Value = productcategoryid; command.Parameters.Add("@ProductEmployeeID", SqlDbType.Int).Value = productemployeeid; // 数据库里ProductCreatedDate已经设置了DEFAULT GETDATE(),所以不用手动传值 conn.Open(); command.ExecuteNonQuery(); } } }
2. 主方法的健壮性优化
原来的int.Parse如果遇到非数字输入会直接崩溃,建议换成int.TryParse:
static void Main(string[] args) { while (true) { Console.Write("Indtast Produktnavn :"); string productname = Console.ReadLine(); Console.Write("Hvor mange er der på lager? : "); if (!int.TryParse(Console.ReadLine(), out int productstock)) { Console.WriteLine("Ugyldigt tal, prøv igen!"); continue; } Console.Write("Hvilken kategori ID hører produktet til? : "); if (!int.TryParse(Console.ReadLine(), out int productcategoryid)) { Console.WriteLine("Ugyldigt tal, prøv igen!"); continue; } Console.Write("Hvilket medarbejder ID har oprettet produktet? : "); if (!int.TryParse(Console.ReadLine(), out int productemployeeid)) { Console.WriteLine("Ugyldigt tal, prøv igen!"); continue; } try { InsertProduct(productname, productstock, productcategoryid, productemployeeid); Console.WriteLine("Produktet er tilføjet!"); } catch (Exception ex) { Console.WriteLine($"Fejl: {ex.Message}"); Console.ReadKey(); } } }
3. 可选:用Product类封装插入逻辑(面向对象风格)
如果想更贴合面向对象设计,可以修改InsertProduct接收Product对象:
static void InsertProduct(Product product) { using (SqlConnection conn = new Database().connection()) { string sql = @"INSERT INTO Products (ProductName, ProductStock, ProductCategoryID, ProductEmployeeID, ProductCreatedDate) VALUES (@ProductName, @ProductStock, @ProductCategoryID, @ProductEmployeeID, @ProductCreatedDate)"; using (SqlCommand command = new SqlCommand(sql, conn)) { command.Parameters.Add("@ProductName", SqlDbType.NVarChar, 32).Value = product.ProductName; command.Parameters.Add("@ProductStock", SqlDbType.Int).Value = product.ProductStock; command.Parameters.Add("@ProductCategoryID", SqlDbType.Int).Value = product.ProductCategoryID; command.Parameters.Add("@ProductEmployeeID", SqlDbType.Int).Value = product.ProductEmployeeID; command.Parameters.Add("@ProductCreatedDate", SqlDbType.DateTime).Value = product.ProductCreatedDate; conn.Open(); command.ExecuteNonQuery(); } } }
主方法里调用时:
Product newProduct = new Product(productname, productstock, productcategoryid, productemployeeid); InsertProduct(newProduct);
关键注意事项
- 永远使用参数化查询:绝对不要用字符串拼接构建SQL,这是预防SQL注入和语法错误的核心手段。
- 用using管理资源:SqlConnection、SqlCommand都实现了
IDisposable接口,using语句会自动帮你释放资源,避免连接泄漏。 - 利用数据库默认值:像
ProductCreatedDate这样的字段,交给数据库用GETDATE()生成,既能减少代码逻辑,还能避免客户端和服务器时间不一致的问题。 - 处理无效输入:用
TryParse代替Parse,让程序更健壮,不会因为用户输入错误直接崩溃。
内容的提问来源于stack exchange,提问作者user5265806
相关产品推荐
相关产品推荐

