2008-10-10 14 views
3

SqlBulkCopy를 사용하여 프로그래밍 방식으로 Excel에서 SQL Server 2005로 데이터를 내보내고 있습니다. 그것은 위대한 작품, 내가 가진 유일한 문제는 Excel 파일에있는 행 시퀀스를 보존하지 않는다는 것입니다. 주문할 열이 없으므로 Excel 스프레드 시트에 표시된 순서대로 레코드를 삽입하기 만하면됩니다.SqlBulkCopy로 행 순서를 유지하는 방법?

Excel 파일을 수정할 수없고 내가 가지고있는 것을 사용해야합니다. 기존 열을 기준으로 정렬하면 시퀀스가 ​​중단됩니다.

도와주세요.

P. 스프레드 시트에 ID 열 삽입 완료. 내보내기/가져 오기 중에 순서를 유지할 방법이없는 것처럼 보입니다.

+0

SQL 테이블이 본질적으로 순서가 지정되어 있지 않다면 어떤 순서로 삽입 순서가 다른지 자동 증가 열이라고 알 수 있습니까? –

답변

3

"ORDER BY"절을 사용하지 않으면 행 순서가 SQL로 지정되거나 보장되지 않는다고 생각합니다. 빌 본이에 의해 게시물 (http://betav.com/blog/billva/2008/08/sql_server_indexing_tips_and_t.html)에서

: 테이블이 (물리적 순서로 데이터를 저장) 클러스터 된 인덱스가있는 경우에도, SQL 서버 가 보장하지 않습니다 작성자 : 주문을 사용

ORDER BY 절이 이 아닌 한 행이 주문서에 반환됩니다.

정보와 또 다른 링크 :

http://sqlblogcasts.com/blogs/simons/archive/2007/08/21/What-is-the-position-of-a-row--.aspx

0

Excel 스프레드 시트를 CSV로 저장할 수 있으면 모든 스크립팅으로 INSERT 문의 목록을 생성하는 것이 매우 쉽습니다. 스프레드 시트와 동일한 순서로 실행되는 언어. 다음은 그루비의 빠른 예제가 있지만 스크립트 언어는 쉽게 그것을 할 것입니다하지 않을 경우 쉽게 :

def file1 = new File('c:\\temp\\yourSpreadsheet.csv') 
def file2 = new File('c:\\temp\\yourInsertScript.sql') 

def reader = new FileReader(file1) 
def writer = new FileWriter(file2) 

reader.transformLine(writer) { line -> 
    fields = line.split(',') 

    text = """INSERT INTO table1 (col1, col2, col3) VALUES ('${fields[0]}', '${fields[1]}', '${fields[2]}');""" 

} 

그런 다음 데이터베이스에 대해 당신의 "yourInsertScript.sql"를 실행할 수 있으며, 주문 스프레드 시트와 동일합니다 .

0

당신은 또한 데이터를로드하는 동안 테이블에 그 자동 증분 ID 열을 정의 할 수 있습니다. 그렇게하면 나중에 같은 순서로 레코드를 원할 때 정렬 할 수 있습니다.

+3

삽입하는 동안 주문이 뒤섞입니다. 너의 접근 방식은 효과가 없을거야. –

1

많은 연구 끝에 Microsoft에서 소개 한 대량 삽입 명령을 사용하여 행 순서를 유지할 방법이 없다는 것이 분명해 보입니다. ID 열을 가져 오기 파일에 직접 추가하거나 셸 또는 다른 외부 스크립트를 사용하거나 추가하지 않아도됩니다. 마이크로 소프트가 추가 할 필요가있는 (그리고 쉬운) 기능이 될 것 같지만, 10 년이 넘는 시간이 지나도 아무 것도 일어나지 않을 것입니다.

그러나 가져온 파일에서 가져온 파일의 실제 레코드 순서를 유지해야 할 필요가있었습니다. 상위 레코드가 설정된 열이 동일한 값을 갖는 경우 낮은 레코드 레코드보다 우선합니다.

그래서 나는 다른 경로를갔습니다. 내 제약 조건은 다음과 같습니다.

  • 원본 파일을 전혀 변경할 수 없습니다. (나쁜 판례를 설정하십시오!)
  • 외부 스크립트를 사용할 수 없습니다. 너무 복잡한. 그것은 간단한 T-SQL 기반 솔루션이었으며, CMD 실행이 필요하지 않았습니다.이것은 자동화 될 수 있도록 단일 절차에 들어갈 필요가있었습니다.

Powershell을 사용하여 각 행에 정렬 된 삽입 문을 작성한 다음 SQL에서 실행하는 논리가 마음에 들었습니다. 기본적으로 BULK 삽입보다는 개별 삽입을 위해 각 레코드를 큐에 넣었습니다. 예, 작동하지만 매우 느립니다. 종종 500K + 행을 가진 파일이 있습니다. 나는 더 빠른 것을 필요로했다.

그래서 저는 XML을 가로 질렀습니다. 파일을 단일 XML 변수로 직접 대량 업로드하십시오. 이것은 각각이 XML에 추가 될 때 레코드의 순서를 유지합니다. 그런 다음 XML 변수를 구문 분석하고 결과를 표에 삽입하여 동시에 식별 컬럼을 추가하십시오.

: 가져 오기 파일은 표준 텍스트 파일이 각 레코드

내 접근 방식 2 단계가있는 줄 바꿈에 (CHAR (10) CHAR (13) +) 끝나는이라고 가정이 있습니다

  1. 각 레코드를 XML 태그로 캡슐화하는 (OPENROWSET을 사용하여) IMPORT SQL 문을 실행하십시오. 결과를 XML 변수로 캡처하십시오.

  2. 변수를 XML 태그로 테이블에 추가하고 [ID] 열을 추가하십시오.

    --------------------------------- 
    Declare @X xml; 
    --------------------------------- 
    SELECT @X=Cast('<X>'+Replace([BulkColumn],Char(13)+Char(10),'</X><X>')+'</X>' as XML) 
    FROM OPENROWSET (BULK N'\\FileServer\ImportFolder\ImportFile_20170120.csv',SINGLE_CLOB) T 
    --------------------------------- 
    SELECT [Record].[X].query('.').value('.','varchar(max)') [Record] 
    ,ROW_NUMBER() OVER (ORDER BY (SELECT 100)) [ID] 
    --Into #TEMP 
    FROM @X.nodes('X') [Record](X); 
    --------------------------------- 
    
    • XML 태그는 각 라인 피드를 교체합니다.

    • 파일이 줄 바꿈으로 끝나면 끝에 공백 행이 추가됩니다. 마지막 행을 삭제하기 만하면됩니다.

나는 그래서 파일 이름에 전달하고 1 또는 0 (경우에 머리글 행있다)에서 시작하는 ID를 설정할 수 동적 SQL을 사용하여 내 프로 시저에이를 썼다.

약 5 초 만에 300K 개의 레코드 파일에 대해 실행할 수있었습니다.