2010-01-25 6 views
4

이상한 질문. 10,000 개의 레코드를 테이블에 삽입하고 있으며 기본 키는 Identity 필드가 아닙니다. 그래서 일부가 중복되면 10,000을 모두 삽입 할 때 SQL Server 삽입에있는 다음 레코드로 건너 뛰고 중복되지 않도록하는 방법이 있습니까? 나는 정말로 삽입 된 것을 얻지 못하는 복제물을 배려하지 않는다.기본 키 중복 레코드 바이 패스로 다음 삽입

답변

8

"중복 키 무시"옵션을 사용하십시오.

가장 간단한 방법은 SQL Server Management Studio에서 기본 키를 삭제하는 것입니다.

"Index"유형의 새 색인을 만들고 고유성을 "예"로 설정하고 "중복 키 무시"를 "예"로 설정하십시오. 그런 다음 기록을 삽입하십시오. 중복을 제외하고 모두 삽입합니다. 작업이 끝나면이 색인을 삭제하고 기본 키를 다시 만들 수 있습니다.

당신이 TSQL 방법을 원하는 경우, CREATE INDEX 통화에서 IGNORE_DUP_KEY 옵션을 참조하십시오

CREATE INDEX (Transact-SQL)

편집 : 왼쪽을 사용하는 것입니다 또 다른 방법은 당신의 소스 사이에 가입

테이블 및 삽입하려는 레코드와 GROUP BY 절을 사용하여 소스에 존재하지 않는 레코드 만 삽입하십시오. GROUP BY는 새 레코드에서 중복 된 레코드를 제거합니다.

+0

기본 키 ?? – uirn

+1

기본 키가 위반되지 않고 문제가되는 레코드가 전체 대량 삽입을 롤백하지 않고 경고를 생성합니다. – JeffO

0

삽입하는 데 어떤 메커니즘을 사용하는지 알지 못하기 때문에 몇 가지 방법을 생각해보십시오.

1) 모든 레코드를 새 빈 테이블로 대량로드 한 다음 해당 레코드가 기본 테이블에없는 스테이징 테이블에서 실제 테이블로 INSERT를 실행하십시오. 예 : 당신은 SQL 2005 이상을 사용하는 경우

INSERT MyRealTable (PKField, Field1) 
SELECT x.PKField, x.Field1 
FROM MyStagingTable x 
    LEFT JOIN MyRealTable r ON x.PKField = r.PKField 
WHERE r.PKField IS NULL 

2)) (하나가 발생한다 PK 제약 조건 오류를 삼키게 TRY...CATCH 블록에 각 삽입을 포장.

+0

아니요 새 레코드가 기존 레코드의 새 레코드가 아닌 선택됩니다. – uirn

+0

옵션 1을 사용하면 준비 테이블의 PKField 값당 하나의 레코드를 실제 테이블로 가져옵니다. 예 : 준비 테이블에 IDENTITY C 럼을 가질 수 있으며 각 PKField 값의 첫 x 째 인스턴스를 가져올 수 있습니다. – AdaTheDev

2

이 예제 쿼리는 PK1에 의해 중복 행을 건너 뜁니다

INSERT INTO Dest (PK1, Field2) 
SELECT s.PK1, s.F2 
FROM Source s 
WHERE 
(
    SELECT TOP 1 d.PK1 
    FROM Dest d 
    WHERE d.PK1 = s.PK1 
) IS NULL 
5

당신이 중복 무시하는 기본 키를 정의해야합니다

경우 : 성능에 손상을 줄 수 있습니다이 옵션을 사용

CREATE TABLE [dbo].[t2](
     [n] [int] NOT NULL, 
PRIMARY KEY CLUSTERED 
(
     [n] ASC 
)WITH (IGNORE_DUP_KEY = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

을 데이터에 중복되는 부분이 적 으면 IGNORE_DUP_KEY가 삽입 속도를 높일 수 있습니다. 더 많은 양의 중복을 위해, IGNORE_DUP_KEY는 그것들을 상당히 느리게 할 수 있습니다.

INSERT t1(n) 
SELECT n FROM dbo.Numbers 

INSERT t2(n) 
SELECT n FROM dbo.Numbers 

(참고 : 들어오는 데이터가없는 중복이 없다면

CREATE TABLE t1(n INT NOT NULL PRIMARY KEY) 
GO 
CREATE TABLE [dbo].[t2](
     [n] [int] NOT NULL, 
PRIMARY KEY CLUSTERED 
(
     [n] ASC 
)WITH (IGNORE_DUP_KEY = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

이 모두 삽입의 성능이 지속적으로 동일 다음과 같이 나는 모든 관련없는 세부 사항을 제거, 두 개의 테이블을 설정 그 dbo. 번호는 100 만 행을 가지고 있습니다.) 물론, 나는 항상 내 테스트 사이에 두 테이블을 잘라 버렸습니다.수신 데이터가 중복 100 %, 인서트와 있었다면 한편

INSERT t1(n) 
SELECT DISTINCT n FROM(
SELECT n FROM dbo.Numbers 
UNION ALL 
SELECT n FROM dbo.Numbers WHERE n <10000 
) AS t 

INSERT t2(n) 
SELECT n FROM dbo.Numbers 
UNION ALL 
SELECT n FROM dbo.Numbers WHERE n <10000 

: 수신 데이터가 중복 1 % 있었다면

는 IGNORE_DUP_KEY 함께 삽입 일관 약 5 % 더 빠른 수행 IGNORE_DUP_KEY 지속적으로 수행 적어도 300 % 느리게, 200 만 많은 행 세트를 모두 :

INSERT t1(n) 
SELECT DISTINCT n FROM(
SELECT n FROM dbo.Numbers 
UNION ALL 
SELECT n FROM dbo.Numbers 
) AS t 

INSERT t2(n) 
SELECT n FROM dbo.Numbers 
UNION ALL 
SELECT n FROM dbo.Numbers 

을뿐만 아니라 200K 행의 작은 세트 :

INSERT t1(n) 
SELECT DISTINCT n FROM(
SELECT n FROM dbo.Numbers WHERE n<100000 
UNION ALL 
SELECT n FROM dbo.Numbers WHERE n<100000 
) AS t 

INSERT t2(n) 
SELECT n FROM dbo.Numbers WHERE n<100000 
UNION ALL 
SELECT n FROM dbo.Numbers WHERE n<100000 

전반적으로, 나는 특정한 경우에 IGNORE_DUP_KEY를 사용하지 않기로 결정했습니다. 소량의 중복에 대해서는 적은 비용 절감만으로도 대용량의 중복 데이터에 대한 엄청난 성능 저하 위험을 정당화 할 수 없다고 판단했습니다.