C#读取XLSX插入SQL Server时IDENTITY列插入错误排查
解决SQL Server表值参数插入IDENTITY列的错误(错误200)
你遇到的这个报错是两个核心问题叠加导致的,咱们一步步拆解清楚:
问题根源分析
- 数据类型完全不匹配:你的用户定义表类型(UDT)
udtInserimentoDatiExcel里的ID是INT类型的IDENTITY列,但C#代码里却把DataTable的ID列错误定义成了Guid类型——这直接导致表值参数的结构和UDT不兼容,触发了"数据不符合参数表类型"的报错。 - IDENTITY列插入规则冲突:即使类型匹配,你也不需要(也不允许)给UDT里的IDENTITY列传递数据——SQL Server会自动为IDENTITY列生成值,手动插入会触发"INSERT into an identity column not allowed on table variables"的限制。
修正方案
咱们需要从C#代码、UDT定义、存储过程三个层面同步调整:
1. 修正C# DataTable定义
去掉错误的Guid类型定义,并且不需要在DataTable中包含IDENTITY列(因为最终目标表的ID会由SQL Server自动生成,不需要从C#端传递):
// 正确定义DataTable,只保留业务字段 DataTable dt = new DataTable(); dt.Columns.Add("PIPPO", typeof(string)); dt.Columns.Add("PLUTO", typeof(string)); dt.Columns.Add("PAPERINO", typeof(string)); // 填充数据时,仅给业务字段赋值,无需处理ID dt.Rows.Add("A", "B", "C"); dt.Rows.Add("D", "E", "F"); // 表值参数传递逻辑保持不变 SqlCommand sqlcmd = new SqlCommand("InserimentoDatiExcel", sqlcon); sqlcmd.CommandType = CommandType.StoredProcedure; sqlcmd.Parameters.AddWithValue("@product", dt); sqlcon.Open(); sqlcmd.ExecuteNonQuery();
2. 调整用户定义表类型(UDT)
既然不需要从C#传递ID值,直接去掉UDT里的IDENTITY属性和ID列(表值参数只需要承载业务数据):
CREATE TYPE [dbo].[udtInserimentoDatiExcel] AS TABLE( [PIPPO] [varchar](1) NOT NULL, [PLUTO] [varchar](1) NOT NULL, [PAPERINO] [varchar](1) NOT NULL ) GO
3. 更新存储过程
修改INSERT语句,明确指定要插入的字段(避免使用SELECT *,防止后续表结构变化引发问题),让目标表Prova的IDENTITY列自动生成值:
ALTER PROCEDURE [dbo].[InserimentoDatiExcel](@product [udtInserimentoDatiExcel] readonly) AS BEGIN -- 明确排除ID列,由Prova表的IDENTITY自动生成 INSERT INTO Prova (PIPPO, PLUTO, PAPERINO) SELECT PIPPO, PLUTO, PAPERINO FROM @product END
补充说明
如果你的Prova表本身的ID就是IDENTITY列,那完全不需要在UDT里定义ID字段——表值参数只需要传递业务数据,目标表的自增ID由SQL Server自动处理,这样既符合IDENTITY列的设计规范,也彻底避免了类型不匹配和插入权限的问题。
内容的提问来源于stack exchange,提问作者FranPN
相关产品推荐
相关产品推荐

