2012-11-23 13 views
2

BULK INSERT를 사용하여 SQL 데이터베이스로 가져 오는 CSV 파일을 매주받습니다. 임시 테이블에 삽입 한 다음 새 레코드를 삽입하고 수정 된 레코드를 업데이트하여 주 테이블과 병합합니다. 코드는 다음과 같습니다 내가 무엇을 달성하고자하는대량 입력 후 SQL 트리거

BULK INSERT dbo.temp 
FROM 'C:\Users\Administrator\Documents\20120125.csv' 
WITH (FIELDTERMINATOR = ',', ROWTERMINATOR = '\n'); 

MERGE dbo.main AS TargetTable        
USING dbo.temp AS SourceTable      
ON (TargetTable.name = SourceTable.name)     
WHEN NOT MATCHED BY TARGET        
    THEN INSERT (name, age, gender, father, mother, teacher, mathsrating, historyrating, sciencerating, englishrating) 
     VALUES(SourceTable.name, SourceTable.age, SourceTable.gender, SourceTable.father, SourceTable.mother, SourceTable.teacher, SourceTable.mathsrating, SourceTable.historyrating, SourceTable.sciencerating, SourceTable.englishrating) 
WHEN MATCHED            
    THEN UPDATE SET 
     TargetTable.name = SourceTable.name, 
     TargetTable.age = SourceTable.age, 
     TargetTable.gender = SourceTable.gender, 
     TargetTable.father = SourceTable.father, 
     TargetTable.mother = SourceTable.mother, 
     TargetTable.teacher = SourceTable.teacher, 
     TargetTable.mathsrating = SourceTable.mathsrating, 
     TargetTable.historyrating = SourceTable.historyrating, 
     TargetTable.sciencerating = SourceTable.sciencerating, 
     TargetTable.englishrating = SourceTable.englishrating; 

DELETE FROM dbo.temp 

내가 변경된 내용의 역사를 가질 수 있도록 자신의 '이전'값을 갖는 새 테이블에 저장된 업데이트로 덮어 쓰기 기록을하는 것입니다. 나는 SQL에 상당히 익숙하지만 조금 연구했는데 방아쇠가 접근하는 방법 일지 모르지만이 접근 방법에 대한 제안을 환영 할 것입니다.

감사

매트

+0

예, 죄송는 SQL 서버 2012 답장을 – MrMatt

답변

1

병합 문은 output clause을 가지고 그 것이다 테이블, 또는 쿼리의 결과 중 하나를 출력 영향을받는 행.

또한 일치하는 부분에 추가 기준을 지정할 수도 있습니다. 이 경우 모든 값이 기존 행과 동일하면 행을 갱신하지 않도록하십시오. 열이 null 인 경우 (1 != Null)Null을 반환하기 때문에 약간 까다 롭습니다. 귀하의 평점은 음수가 될 수 없다고 가정하면 IsNull(s.rating, -1) != IsNull(t.rating, -1)이 변경되었는지 확인하십시오.

출력 절이 쿼리의 결과가 될 수 있으므로 내부 쿼리로 중첩 할 수 있습니다. 나는 당신의 히스토리 테이블에 UpdateTimestamp을 추가하기 위해 이것을 사용했다.

예 : NULL 체크가 필요한 이유의 http://sqlfiddle.com/#!6/1651a/2

예 : http://sqlfiddle.com/#!6/bd99b/2

Insert Into 
    history_table 
Select 
    GetDate(), [name], age, gender, father, mother, teacher, 
    mathsrating, historyrating, sciencerating, englishrating 
From (
    Merge 
    dbo.main As t 
    Using 
    dbo.temp AS s 
     On (t.[name] = s.[name]) 
    When Not Matched By Target Then 
    Insert (
     [name], age, gender, father, mother, teacher, 
     mathsrating, historyrating, sciencerating, englishrating 
    ) values (
     s.[name], s.age, s.gender, s.father, s.mother, s.teacher, 
     s.mathsrating, s.historyrating, s.sciencerating, s.englishrating 
    ) 
    When Matched And -- assume ratings can't be negative, but can be null 
    t.age != s.age Or 
    t.gender != s.gender Or 
    t.father != s.father Or 
    t.mother != s.mother Or 
    t.teacher != s.teacher Or 
    IsNull(t.mathsrating, -1) != IsNull(s.mathsrating, -1) Or 
    IsNull(t.historyrating, -1) != IsNull(s.historyrating, -1) Or 
    IsNull(t.sciencerating, -1) != IsNull(s.sciencerating, -1) Or 
    IsNull(t.englishrating, -1) != IsNull(s.englishrating, -1) 
    Then Update 
    Set 
     t.[name] = s.[name], 
     t.age = s.age, 
     t.gender = s.gender, 
     t.father = s.father, 
     t.mother = s.mother, 
     t.teacher = s.teacher, 
     t.mathsrating = s.mathsrating, 
     t.historyrating = s.historyrating, 
     t.sciencerating = s.sciencerating, 
     t.englishrating = s.englishrating 
    Output 
     $action as Action, deleted.* 
) as Updates 
+0

감사합니다. 나는 이것을 시도했지만 history_table은 0 행을 반환했다. dbo.main 및 dbo.temp에있는 동일한 열을 사용하여 history_table을 만들었습니다 -이게 무슨 뜻입니까? – MrMatt

+0

그것이 내가 의미했던 것입니다. 여기에 언급 된 출력 테이블에는 몇 가지 제한 사항이 있습니다. http://technet.microsoft.com/ko-kr/library/ms177564.aspx 특히 트리거가없고 외래 키도없고 점검 제약도 없습니다. 또한 ID 열이나 계산 열이있는 경우 열을 명시 적으로 지정해야 할 수도 있습니다. – Laurence

+0

감사. 내가 0 행을 반환하는 이유는 내가 실험을하는 동안 메인 테이블에 트리거를 남겨 두었 기 때문입니다. 트리거를 제거하면 행이 반환되지만 예상대로 작동하지 않습니다. 히스토리 테이블은 임시 테이블과 동일한 수의 행을 포함합니다. – MrMatt