[SQL] 기본 키가없는 경우 중복 레코드가 SqlBulkCopy의 삽입되지 않도록하는 방법
SQL기본 키가없는 경우 중복 레코드가 SqlBulkCopy의 삽입되지 않도록하는 방법
나는 각 내가보고 및 결제에 사용하기 위해 내부 데이터베이스에 저장해야하는 비즈니스 트랜잭션되고, 수천 개의 레코드를 포함하는 일상 XML 파일을받을 수 있습니다. 나는 매일의 파일은 고유 한 기록을 포함하지만, 고유의 나의 정의는 정확히 제공 업체의 동일하지 않습니다 것을 발견하는 인상이었다.
이 데이터는 C # 닷넷 3.5 콘솔 응용 프로그램입니다 수입하는 현재의 응용 프로그램은,이 때문에 MS SQL 서버 2008 데이터베이스 테이블에 SqlBulkCopy의를 사용하면 열이 정확하게 XML 레코드의 구조와 일치 않는 경우. 각 레코드는 100 개 이상의 필드가, 나는 복합 키 말까지도 널 (null)을 허용하는 것으로 이해하고 함께 올 수있는 데이터에는 자연 키, 또는 오히려 분야가 없습니다. 현재 테이블이 여러 인덱스,하지만 기본 키를 가지고있다.
기본적으로 전체 행은 고유해야합니다. 하나 개의 필드가 다른 경우 삽입 할 유효한 충분하다. 난하지만 난 대량 복사 작업에 MD5 해시를 얻는 방법을 볼 수 없습니다, 데이터베이스에와 행을 삽입에서 SqlBulkCopy의 방지를 위해 제약 조건을 사용하여 해당 삽입, 전체 행의 MD5 해시를 만들어 보면서 나는 아니에요 반드시 전체 작업이 실패하고 롤 다시 어떤 하나 개의 레코드가 실패 할 경우, 또는 계속하면 것인지.
이 파일은 정말 내가이 일을 할 수있는 볼 수있는 유일한 방법은 아주 많은 레코드가, XML에서 행 단위로가는 모든 필드와 일치하는 레코드에 대한 데이터베이스를 조회 한 다음 삽입에 결정이 포함되어 있습니다. 난 그냥 완전히 응용 프로그램을 다시 작성해야하지 기대했다, 그리고 대량 복사 작업이 훨씬 더 빨리 너무입니다.
기본 키없이, 중복 행을 방지하면서 방법의 사람을 알고는 SqlBulkCopy의를 사용합니까? 아니면 다른 방법에 대한 어떤 제안이 작업을 수행하려면?
해결법
-
==============================
1.나는 그 준비 테이블에 데이터를 업로드 최종 테이블에 복사본 이후 중복 다룰 것입니다.
나는 그 준비 테이블에 데이터를 업로드 최종 테이블에 복사본 이후 중복 다룰 것입니다.
예를 들어, "키"로 거래를 준비 테이블에 (고유하지 않은) 인덱스를 만들 수 있습니다
-
==============================
2.당신은 SQL 2008을 사용하고 있음을 감안할 때, 당신은 (전혀 경우) 많은 응용 프로그램을 변경할 필요없이 쉽게 문제를 해결하기 위해 두 가지 옵션이 있습니다.
당신은 SQL 2008을 사용하고 있음을 감안할 때, 당신은 (전혀 경우) 많은 응용 프로그램을 변경할 필요없이 쉽게 문제를 해결하기 위해 두 가지 옵션이 있습니다.
첫 번째 가능한 해결책은 처음처럼하지만 대리 신원 키와 당신을 위해 중복 제거의 모든 무거운 리프팅을 할 것 IGNORE_DUP_KEY 옵션을 사용하여 추가 된 고유성 제약 조건 두 번째 테이블을 만드는 것입니다.
여기에 무슨 일이 일어나고 있는지 볼 수 SSMS에서 실행할 수있는 예입니다 :
if object_id( 'tempdb..#test1' ) is not null drop table #test1; if object_id( 'tempdb..#test2' ) is not null drop table #test2; go -- example heap table with duplicate record create table #test1 ( col1 int ,col2 varchar(50) ,col3 char(3) ); insert #test1( col1, col2, col3 ) values ( 250, 'Joe''s IT Consulting and Bait Shop', null ) ,( 120, 'Mary''s Dry Cleaning and Taxidermy', 'ACK' ) ,( 250, 'Joe''s IT Consulting and Bait Shop', null ) -- dup record ,( 666, 'The Honest Politician', 'LIE' ) ,( 100, 'My Invisible Friend', 'WHO' ) ; go -- secondary table for removing duplicates create table #test2 ( sk int not null identity primary key ,col1 int ,col2 varchar(50) ,col3 char(3) -- add a uniqueness constraint to filter dups ,constraint UQ_test2 unique ( col1, col2, col3 ) with ( ignore_dup_key = on ) ); go -- insert all records from original table -- this should generate a warning if duplicate records were ignored insert #test2( col1, col2, col3 ) select col1, col2, col3 from #test1; go
또한, 당신은 또한 두 번째 테이블없이 현재 위치에서 중복을 제거 할 수 있지만 성능은 사용자의 요구에 너무 느릴 수 있습니다. 여기에 SSMS에서 실행 가능한 또한 예를 들어 코드입니다 :
if object_id( 'tempdb..#test1' ) is not null drop table #test1; go -- example heap table with duplicate record create table #test1 ( col1 int ,col2 varchar(50) ,col3 char(3) ); insert #test1( col1, col2, col3 ) values ( 250, 'Joe''s IT Consulting and Bait Shop', null ) ,( 120, 'Mary''s Dry Cleaning and Taxidermy', 'ACK' ) ,( 250, 'Joe''s IT Consulting and Bait Shop', null ) -- dup record ,( 666, 'The Honest Politician', 'LIE' ) ,( 100, 'My Invisible Friend', 'WHO' ) ; go -- add temporary PK and index alter table #test1 add sk int not null identity constraint PK_test1 primary key clustered; create index IX_test1 on #test1( col1, col2, col3 ); go -- note: rebuilding the indexes may or may not provide a performance benefit alter index PK_test1 on #test1 rebuild; alter index IX_test1 on #test1 rebuild; go -- remove duplicates with ranks as ( select sk ,ordinal = row_number() over ( -- put all the columns composing uniqueness into the partition partition by col1, col2, col3 order by sk ) from #test1 ) delete from ranks where ordinal > 1; go -- remove added columns drop index IX_test1 on #test1; alter table #test1 drop constraint PK_test1; alter table #test1 drop column sk; go
-
==============================
3.나는 임시 테이블로 대량 복사를하고자 다음 실제 대상 테이블에 그에서 데이터를 밀어 넣습니다. 이러한 방법으로, 당신은과 핸들 중복 확인하기 위해 SQL을 사용할 수 있습니다.
나는 임시 테이블로 대량 복사를하고자 다음 실제 대상 테이블에 그에서 데이터를 밀어 넣습니다. 이러한 방법으로, 당신은과 핸들 중복 확인하기 위해 SQL을 사용할 수 있습니다.
-
==============================
4.이유는 간단하게, 대신 기본 키의 사용 인덱스 및 세트를 만들 수 없습니다
이유는 간단하게, 대신 기본 키의 사용 인덱스 및 세트를 만들 수 없습니다
Ignore Duplicate Keys: YES
이 오류가 발생하는 중복 키를 방지하며, (이미 존재하는)이 작성되지 않습니다.
나는 완벽 주위 120.000 하루 행과 작품을 삽입하기 위해이 방법을 사용합니다.
-
==============================
5.데이터 볼륨은 무엇인가? 당신은 내가 볼 수있는 두 가지 옵션이 있습니다 :
데이터 볼륨은 무엇인가? 당신은 내가 볼 수있는 두 가지 옵션이 있습니다 :
1 : 자신의 IDataReader에 구현하고 데이터에 어떤 해시를 사용하여, 단순히 그들이 TDS에 전달되지는 결코 그렇게 모든 중복을 건너 뛰는하여 소스에서 필터를.
2 : DB에서 필터; 원시, unsanitised 데이터 - - 그리고 당신이 원하는 경우 아마도 중간 테이블을 사용하여, 실제 테이블에 DISTINCT 데이터를 복사하는 가장 간단한 수준에서, 나는 당신이 수입의 여러 단계가있을 것 같아요. 이 중 일부 CHECKSUM을 사용할 수 있습니다,하지만 따라 달라집니다.
-
==============================
6.그리고 그 테이블을 수정. 어떤 테이블은 이제까지 바람직하게는 PK로, 고유 인덱스없이 없어야합니다. 자연적인 키가 없기 때문에 당신이 대리 키를 추가 할 경우에도 특히 특정 레코드를 식별 할 수 있어야합니다. 그렇지 않으면 방법은 당신이 이미 가지고있는 중복 제거 것인가?
그리고 그 테이블을 수정. 어떤 테이블은 이제까지 바람직하게는 PK로, 고유 인덱스없이 없어야합니다. 자연적인 키가 없기 때문에 당신이 대리 키를 추가 할 경우에도 특히 특정 레코드를 식별 할 수 있어야합니다. 그렇지 않으면 방법은 당신이 이미 가지고있는 중복 제거 것인가?
-
==============================
7.나는이 많은 청소기라고 생각합니다.
나는이 많은 청소기라고 생각합니다.
var dtcolumns = new string[] { "Col1", "Col2", "Col3"}; var dtDistinct = dt.DefaultView.ToTable(true, dtcolumns); using (SqlConnection cn = new SqlConnection(cn) { copy.ColumnMappings.Add(0, 0); copy.ColumnMappings.Add(1, 1); copy.ColumnMappings.Add(2, 2); copy.DestinationTableName = "TableNameToMapTo"; copy.WriteToServer(dtDistinct ); }
이 방법은 하나 개의 데이터베이스 테이블을 필요로하고 코드에서 비즈니스 로직을 유지할 수 있습니다.
from https://stackoverflow.com/questions/2593689/how-to-prevent-duplicate-records-being-inserted-with-sqlbulkcopy-when-there-is-n by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 윈도우 함수의 FILTER 절에서 현재 행을 참조하기 (0) | 2020.07.05 |
---|---|
[SQL] SQL : 마 당신은 많은-많은 테이블의 자동 증가 기본 키를해야합니까? (0) | 2020.07.05 |
[SQL] C #에서 SQL을 대량 복사 / 삽입 (0) | 2020.07.05 |
[SQL] 모든 칼럼에 null 값 (들)의 모든 행을 찾기 (0) | 2020.07.05 |
[SQL] 업데이트 트리거 후 SQL 서버 (0) | 2020.07.05 |