부모 / 자식 관계가있는 SQL 대량 삽입은 순서가 유지됩니까?

c# sqlbulkcopy sql-server-2008

문제

아래에 언급 된 다른 질문과 마찬가지로이 구조에는 두 개의 테이블이 있습니다.

create table parent (
   recno int identity(1,1) primary key not null,
   groupCode int,
   parentdata varchar(80)
);

create table child (
   parentrecno int not null,
   childdata varchar(80)
)

이 테이블에 수십만 개의 레코드를 신속하게 삽입해야합니다.이 테이블에는이 삽입과 관련이없고 수백만 개의 다른 레코드가 저장되어 있습니다. 부모 / 자식 특성 때문에 SqlBulkCopy 대한 좋은 후보는 아닙니다.

C #에서 INSERT SqlCommand 를 사용하면 삽입되는 초당 약 400-500 개의 레코드가 생기고 이것은 약간 느립니다. 의사 코드 :

 foreach(Record r in parentRecords)
 {
      Insert Fields from r into SqlCommand Parameters but not "recno"
      Call ExecuteScalar to insert and fetch the inserted identity value (recno)
      foreach(ChildRecord cr in parentRecords.Children)
      {
          Insert Fields from cr into SqlCommand Parameters
          Insert the identity value (recno) from above into Parameters 
                                                       (as parentrecno)
          Call ExecuteNonQuery to insert the record
      }   
 }

그 다른 게시물을 읽은 후에도 나에게 일어났다. 상위 레코드에 첨부 된 groupCode 는 삽입하려는 상위 레코드 세트에 고유합니다. 그것은 작동할까요?

  1. SqlBulkCopy 하여 부모 레코드를 대량 삽입하여 insert가 recno ID 필드를 평소대로 자동 생성하도록합니다.
  2. 삽입 된 레코드에 대해서만 SELECT 를 수행하십시오.

    select recno from parent where groupCode = @thisgroup order by recno;
    
  3. 검색된 값을 사용하여 메모리의 하위 레코드에 대한 parentrecno 필드를 채 웁니다.

  4. SqlBulkCopy 하여 하위 레코드 대량 삽입

이는 원래 DataTable에있는 것과 동일한 순서로 SQL 테이블로 이동하는 상위 레코드 (및 동일한 순서로 할당되는 ID 값)에 의존합니다. 내가 의지 할 수있는 것입니까?

관련 질문 :

자동 생성 ID 키로 데이터 세트 부모 및 자식 테이블을 업데이트하는 방법

식별 열에 대한 부모 / 자식 관계가있는 SqlBulkCopy 및 DataTables

수락 된 답변

목표 테이블과 동일한 구조로 두 개의 스테이징 테이블을 작성하지만 recno 컬럼에서는 ID를 사용하지 마십시오.

create table parentTmp (
   recno int,
   groupCode int,
   parentdata varchar(80)
);

create table childTmp (
   parentrecno int not null,
   childdata varchar(80)
)

recno / parentrecno 값을 그대로 유지하면서 스테이징 테이블에 데이터를 대량로드하십시오.

그런 다음 병합출력 을 사용하여 스테이징 테이블에서 데이터를 이동할 수 있습니다.

-- Table variable to hold mapping between 
-- SourceRecno and TargetRecno
declare @recno table(SourceRecno int, TargetRecno int);

-- Merge data from parentTmp to parent
-- Output old and new recno to @recno
merge parent T
using parentTmp S
on 0=1
when not matched then
  insert (groupCode, parentdata)
    values (S.groupCode, S.parentData)
output S.recno, inserted.recno into @recno;

-- Copy data from childTmp to child
-- Use @recno to get the new recno
insert into child(parentrecno, childdata)
select R.TargetRecno, C.childdata
from childTmp as C
  inner join @recno as R
    on C.parentrecno = R.SourceRecno;

이것은 SQL Server 2008에서만 작동합니다 (나중에 추측합니다).


인기 답변

이것은 절대 대량 삽입이 아니며 대신 부모 데이터와 동시에 모든 하위 데이터를 삽입하여 DB에 대해 왕복 1 회만 수행합니다.

insert into parent(groupcode, parentdata) values(1, 'parent data');
insert into child(parentrecno, childdata) select parentrecno, childdata from (
    select SCOPE_IDENTITY() as parentrecno, 'child data 1' as childdata
    union
    select SCOPE_IDENTITY() as parentrecno, 'child data 2' as childdata
    union
    select SCOPE_IDENTITY() as parentrecno, 'child data 3' as childdata
) childrendata;

C # 코드에서 이와 같은 스크립트를 작성한 다음 부모 당 하나의 요청을 수행 할 수 있습니다.

자식 데이터의 양이 많은 것으로 알려진 경우 이는 좋은 접근 방식이 아닐 수 있습니다. 세부 사항을 모르겠지만 SQL 스크립트의 크기가 무한정 커질 수는 없습니다.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.