通过C#SqlCommand执行合并语句不起作用

我正在尝试使用临时表和MERGE语句通过C#中的SqlCommand对象更新SQL表。 我正在处理的程序旨在首先将一组非常大的记录(超过20k +)导出到Excel电子表格中。 然后,用户能够搜索并替换特定值,并在他们喜欢的记录中更新尽可能多的字段。

我正在尝试的是获取该电子表格,使用它填充DataTable ,然后使用SqlBulkCopy使用DataTable填充临时SQL表。

然后,如果行仍存在于数据库中,则使用MERGE语句更新行。

但是,我遇到的问题是我在ZipCodeTerritory表上的唯一约束一直被触发给我以下错误消息:

无法在对象’dbo.ZipCodeTerritory’中插入具有唯一索引’UQ_ChannelStateEndDateZipCodeISNULL’的重复键行。 重复键值为(9,CA,94351,9999-12-31)。

这使我相信某种方式UPDATE语句没有被执行或者我在某种程度上使用ON关键字错误地加入了表中的表。 唯一约束仅在INSERT语句期间触发,或者在ChannelCodeStateCodeZipCodeEndDate字段的UPDATE期间触发。 我正在对IndDistrnId字段进行批量更新,并彻底检查了电子表格。

再次,这是我尝试这种技术的第一次尝试,所以任何帮助/建议将不胜感激。 谢谢

C#

 private static string updateCommand = "UPDATE SET Target.ChannelCode = Source.ChannelCode, Target.DrmTerrDesc = Source.DrmTerrDesc, Target.IndDistrnId = Source.IndDistrnId," + "Target.StateCode = Source.StateCode, Target.ZipCode = Source.ZipCode, Target.EndDate = Source.EndDate, Target.EffectiveDate = Source.EffectiveDate," + "Target.LastUpdateId = Source.LastUpdateId, Target.LastUpdateDate = Source.LastUpdateDate, Target.ErrorCodes = Source.ErrorCodes," + "Target.Status = Source.Status "; //Load updates into datatable DataTable table = LoadData(updates); //Script to create temp table string tmpTable = "CREATE TABLE [dbo].[ZipCodeTerritoryTemp]( " + "[ChannelCode] [char](1) NOT NULL, " + "[DrmTerrDesc] [nvarchar](30) NOT NULL, " + "[IndDistrnId] [char](3) NULL, " + "[StateCode] [char](3) NOT NULL, " + "[ZipCode] [char](9) NULL, " + "[EndDate] [date] NOT NULL, " + "[EffectiveDate] [date] NOT NULL, " + "[LastUpdateId] [char](8) NULL, " + "[LastUpdateDate] [date] NULL, " + "[Id] [int] IDENTITY(1,1) NOT NULL, " + "[ErrorCodes] [varchar](255) NULL, " + "[Status] [char](1) NULL, " + "CONSTRAINT [PK_ZipCodeTerritoryTemp] PRIMARY KEY NONCLUSTERED " + "( " + "[Id] ASC " + ")WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY] " + ") ON [PRIMARY]"; using (SqlConnection connection = new SqlConnection(connString)) { connection.Open(); //Create temp table SqlCommand cmd = new SqlCommand(tmpTable, connection); cmd.ExecuteNonQuery(); try { using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) { //Write to temp table bulkCopy.DestinationTableName = "ZipCodeTerritoryTemp"; bulkCopy.WriteToServer(table); //Merge changes in temp table with ZipCodeTerritory string mergeSql = "merge ZipCodeTerritory as Target " + "using ZipCodeTerritoryTemp as Source " + "on " + "Target.Id = Source.Id " + "when matched then " + updateCommand + ";"; cmd.CommandText = mergeSql; int results = cmd.ExecuteNonQuery(); //Drop temp table cmd.CommandText = "DROP TABLE [dbo].[ZipCodeTerritoryTemp]"; cmd.ExecuteNonQuery(); } } catch (Exception) { throw; } finally { //Drop temp table SqlCommand final = new SqlCommand("DROP TABLE [dbo].[ZipCodeTerritoryTemp]", connection); final.ExecuteNonQuery(); } } 

SQL

为了便于阅读,这里是我在SQL Server Management Studio中编写的MERGE语句。 我将其复制到C#中。 仅供参考 – 在Management Studio中运行此语句并收到完全相同的错误消息。

 MERGE INTO ZipCodeTerritory as Target USING ZipCodeTerritoryTemp as Source ON Target.Id = Source.Id WHEN MATCHED THEN UPDATE SET Target.ChannelCode = Source.ChannelCode, Target.DrmTerrDesc = Source.DrmTerrDesc, Target.IndDistrnId = Source.IndDistrnId, Target.StateCode = Source.StateCode, Target.ZipCode = Source.ZipCode, Target.EndDate = Source.EndDate, Target.EffectiveDate = Source.EffectiveDate, Target.LastUpdateId = Source.LastUpdateId, Target.LastUpdateDate = Source.LastUpdateDate, Target.ErrorCodes = Source.ErrorCodes, Target.Status = Source.Status; 

最后一个问题是在临时表中的Id字段上设置的IDENTITY属性。 删除后,我能够无误地运行MERGE 。 这是临时表:

 //Script to create temp table string tmpTable = "CREATE TABLE [dbo].[ZipCodeTerritoryTemp]( " + "[ChannelCode] [char](1) NOT NULL, " + "[DrmTerrDesc] [nvarchar](30) NOT NULL, " + "[IndDistrnId] [char](3) NULL, " + "[StateCode] [char](3) NOT NULL, " + "[ZipCode] [char](9) NULL, " + "[EndDate] [date] NOT NULL, " + "[EffectiveDate] [date] NOT NULL, " + "[LastUpdateId] [char](8) NULL, " + "[LastUpdateDate] [date] NULL, " + "[Id] [int] NOT NULL, " + //DO NOT GIVE THE PK OF THE TEMP TABLE AN IDENTITY(1,1,) PROPRETY "[ErrorCodes] [varchar](255) NULL, " + "[Status] [char](1) NULL, " + "CONSTRAINT [PK_ZipCodeTerritoryTemp] PRIMARY KEY NONCLUSTERED " + "( " + "[Id] ASC " + ")WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY] " + ") ON [PRIMARY]";