为什么我在 MERGE 语句上收到间歇性重复更新错误,而这是不可能的
本文关键字:错误 更新 不可能 语句 MERGE 为什么 | 更新日期: 2023-09-27 18:34:35
我有以下代码:
// accessedKeys is a HashSet<string>
if (accessedKeys.Count > 0)
{
string queryFormat = @"SET NOCOUNT ON;
DECLARE @updated_resources TABLE (name varchar(512))
INSERT INTO @updated_resources (name) VALUES ('{0}')
MERGE resource_access WITH (HOLDLOCK) AS target
USING @updated_resources AS source
ON target.name = source.name
WHEN MATCHED THEN
UPDATE SET last_access = GETDATE()
WHEN NOT MATCHED THEN
INSERT (name, last_access) VALUES (source.name, GETDATE());";
string entries = String.Join("'),('", accessedKeys.Select(s => s.Replace("'", "''")));
string query = String.Format(queryFormat, entries);
using (var connection = new SqlConnection(...))
{
connection.Open();
using (var cmd = connection.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
}
accessedKeys.Clear();
}
resource_access
是这样创建的:
CREATE TABLE resource_access (
name varchar(512) primary key,
last_access smalldatetime not null
)
在执行语句期间,我间歇性地收到以下异常:
The MERGE statement attempted to UPDATE or DELETE the same row more than
once. This happens when a target row matches more than one source row. A
MERGE statement cannot UPDATE/DELETE the same row of the target table
multiple times. Refine the ON clause to ensure a target row matches at most
one source row, or use the GROUP BY clause to group the source rows.
@updated_resources.name
是从不同字符串列表中填充的,resource_access.name
是主键,这意味着它也是唯一的。我正在合并两个表的name
列,两者都不能有重复的条目。
如果我中断异常,accessedKeys.Distinct().Count
等于accessedKeys.Count
.如果我执行SELECT COUNT(DISTINCT(name)) FROM resource_access
,它等于表中的行数。
为什么我有时会收到此错误?
您是否使用不区分大小写的搜索检查过名称是否不同?您提供的用于查找非重复值的 C# 区分大小写。根据您在数据库中设置的排序规则,MERGE 将不区分大小写进行查找。因此,如果您的表具有名称"Bob",并且传入数据同时具有"Bob"和"BOB",则会收到此错误。
试试这个:
accessedKeys.Distinct(StringComparer.CurrentCultureIgnoreCase).Count()