2010-03-09 4 views
3

SQL Server에서 XML 형식 열을 사용하여 메시지를 저장하고 있습니다. 중복 메시지를 저장하고 싶지 않습니다.SQL Server XML 형식 열 중복 항목 검색

사용자 당 몇 개의 메시지 만 있습니다. 현재이 메시지에 대한 테이블을 쿼리하고 XML을 C# 코드의 문자열로 변환합니다. 그런 다음 문자열을 내가 삽입하려고하는 것과 비교합니다.

불행히도 SQL Server는 XML 입력 필드에 데이터를 출력합니다. 데이터베이스에 저장하는 내용이 나중에 다시 나오는 것과 정확히 같은 문자열 일 필요는 없습니다.

나는 데이터베이스에 이미 그들과 함께 삽입 고려하고 XML 문자열을 비교하기위한 효율적인 방법이 있나요 등이 기능적으로 동일하지만 공백은 제거 할 수도? 제쳐두고, 중복을 발견하면 이전 메시지를 삭제하고 대체 메시지를 삽입해야합니다.

+0

+1 좋은 질문! 그것은 XML의 까다로운 측면 중 하나입니다. 쉬운 해결책이 아닙니다. 저는 두려워요 ... –

+0

관심을 잃었습니까? 더 나은 해결책을 찾았습니까? –

+0

@ p.marino : 아니요, 전혀 관심을 잃지 않았습니다. 나는 당신의 솔루션을 받아들이고 싶습니다만, 이미 데이터베이스에있는 것의 해쉬를 저장하는 것은 옳지 않은 것처럼 보입니다. XML 형식 필드의 사용을 포기하고 varchar로 돌아갑니다. 나는 이것을 '해결책'으로 추가 하겠지만, 나는 그 중 하나를 받아들이지 않을 것입니다. –

답변

2

0 - 테이블

1 해시 열을 추가 - 새 메시지를받을 때, 모든 공백 및 반품/줄 바꿈 제거, 대문자로 전체 XML로 변환 한 후 정규화 된 문자열의 해시 값을 계산 .

2 - 이미 해시 코드가 포함 된 행이 있는지 확인하십시오. 예,이 중복되는

  • 경우, 그것은
  • 그렇지 않으면 따라 치료
+0

주의 사항 : 해시 코드가 있기 때문에 값이 같지 않아도되지만 SHA1 또는 MD5 등을 사용하면 충돌 위험이 무시할 수 있습니다. 논픽션 주 : 아마도이 계산을 수행하는 함수 (아마도 CLR)를 만들고, 값에 대해 계산 된 열을 만들고, 계산 된 열에 고유 한 인덱스를 만들 수도 있습니다. – erikkallen

+1

@erikallen : CLR 기능 필요없이, 단지 내장 HASHBYTES http://msdn.microsoft.com/en-us/library/ms174415.aspx –

+0

내가 문자열 정상화 할 필요가 있다고 생각하지 않는다, 당신의 단계를 사용 1.난 원시 메시지 문자열에 해시를 계산할 수 있습니다, 그리고 중복에 대한 비교는 여전히 정확합니다. 내 중복 테스트는 저장할 원본 메시지의 중복을 검색하는 것입니다. ("Hello"는 "HELLO"와 같지 않아야합니다). –

0

하나의 솔루션이 입력 된 XML의 사용을 중지하는 것입니다 새 행에 해시와 함께 원래의 XML 저장 들. XML 문자열을 varchar 유형 필드에 저장하십시오.

나는이 솔루션처럼 정말 할,하지만 난 하나 p.marino의 솔루션처럼 정말하지 않습니다. 이미 테이블에있는 행에있는 항목의 해시를 저장하는 것이 옳지 않은 것 같습니다.

0

당신이 테이블의 각 행에 OPENXML을 사용하여 키 노드 및/또는 주요 특성에 대한 실제 XML 정보를 조회 할 경우? 그렇지만 행별로 행할 필요가 있습니다. OPENXML이 전체 테이블 행 집합과 함께 작동한다고 생각하지 않습니다.

1

정확한 구현에 대해서는 100 % 확신 할 수 없지만 여기에 나와 함께 해보았습니다. 스토어드 프로 시저라는 아이디어는 삽입 작업을 수행합니다. 메시지 테이블에 삽입하면 기존 메시지 (SQL 2008 구문)에 대한 기본 검사가 수행됩니다.

declare @messages table (msg xml) 
insert into @messages values 
('<message>You like oranges</message>') 
,('<message>You like apples</message>') 

declare @newMessage xml = '<message>You like apples</message>' 

insert into @messages (msg) 
select @newMessage 
where @newMessage.value('(message)[1]', 'nvarchar(50)') not in (
    select msg.value('(message)[1]', 'nvarchar(50)') 
    from @messages 
)