2014-12-17 1 views
1

나는 다음과 같은 코드가 있습니다MERGE 문에서 간헐적 인 중복 업데이트 오류가 발생하는 이유는 무엇입니까?

// 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은 기본 키입니다. y는 고유 한 의미이기도합니다. 두 테이블 'name 열에 모두 병합 중이며 둘 다 중복 항목이있을 수 있습니다.

예외가 발생하는 경우 accessedKeys.Distinct().CountaccessedKeys.Count과 같습니다. SELECT COUNT(DISTINCT(name)) FROM resource_access을 실행하면 테이블의 행 수와 같습니다.

때때로이 오류가 발생합니까?

+0

좀 더미 데이터를 시도 할 것입니다, 당신은 어떻게 발생 어디에/좁힐 수없는 경우를 참조하십시오. 즉 resource_access 테이블에 'Bob'을 가지고 있으며이 경우 액세스 된 키 집합에 'Bob'과 'BOB'가 모두있어 오류의 원인인지 아닌지 확인하십시오. 다행히도 그것은 의미가 있습니다. – Trent

답변

2

이름이 대소 문자를 구분하지 않는 검색으로 구분되어 있는지 확인 했습니까? 별개의 값을 찾기 위해 지정한 C#은 대소 문자를 구분합니다. 데이터 베 이스에 설정 한 데이터 정렬에 따라 MERGE는 해당 데이터를 조회 할 때 대/소문자를 구분하지 않습니다. 테이블에 'Bob'이라는 이름이 있고 들어오는 데이터에 'Bob'과 'BOB'가 있으면이 오류가 발생합니다.

대신을 시도

accessedKeys.Distinct(StringComparer.CurrentCultureIgnoreCase).Count() 
+0

감사합니다. 왜 그런 생각을하지 않았는지 모르겠습니다. –

+0

당신이 인간이기 때문에 그렇게 될 것입니다 (적어도 나는 당신이라고 생각합니다). –

관련 문제