본문 바로가기

데이터 엑세스

[FireDAC MergeDataSet] 여러 데이터셋을 병합해 하나의 데이터셋을 구성할 수 있습니다.

FireDAC의 TFDDataSet.MergeDataSet 메소드를 이용해 구조가 같은(또는 확장된) 데이터셋을 병합해 하나의 데이터셋을 구성할 수 있습니다.


제가 테스트한 목적은, 

데이터스냅으로 데이터량이 많은 데이터 중 일부분 데이터만 가져오고, 필요한 경우 추가로 가져와 병합(페이징 기능 구현) 할 목적으로 테스트 진행해 봤습니다.

TFDDataSet.MergeDataSet

지정된 데이터 셋(ASource)의 데이터와 메타데이터를 현재 데이터셋과 병합합니다.

procedure MergeDataSet(ASource: TFDDataSet; AData: TFDMergeDataMode = dmDataMerge; AMeta: TFDMergeMetaMode = mmNone);


TFDMergeDataMode

데이터셋 데이터를 병합하는 방법 지정

모드설명

데이터셋 변경 사항 커밋

dmNone

데이터를 병합하지 않습니다.

-

dmDataSet

원 데이터셋 클리어 후 지정된 데이터셋의 레코드를 대신 삽입합니다.

dmDataAppend

지정된 데이터셋의 레코드를 원 데이터셋에 덧붙입니다.

dmDataMerge

지정된 데이터셋의 레코드의 기본 키를 취득하고 그것과 같은 기본 키 대응 레코드를 원 데이터셋에서 찾습니다. 그 후 다음 중 하나를 수행합니다.

  • 이 데이터셋의 레코드에 해당하는 레코드가 지정된 데이터셋에있는 경우, 해당 레코드에서이 데이터셋의 레코드를 업데이트합니다.
  • 지정된 데이터셋의 레코드에 해당하는 레코드가이 데이터셋에 없는 경우는 지정된 데이터셋의 레코드가 새 레코드로이 데이터셋에 추가됩니다.
  • 해당 레코드가 삭제 된 레코드가 있으면 그것을 삭제합니다.

dmDeltaSet

원 데이터셋을 지우고 지정된 데이터셋의 레코드를 대신 삽입합니다.

아니오

dmDeltaAppend

지정된 데이터셋의 레코드를 원 데이터셋에 덧붙입니다.

아니오

dmDeltaMerge

지정된 데이터셋의 레코드의 기본 키를 취득하고 그것과 같은 기본 키 대응 레코드를 원 데이터셋에서 찾습니다. 그 후 다음 중 하나를 수행합니다.

  • 이 데이터셋의 레코드에 해당하는 레코드가 지정된 데이터셋에있는 경우, 해당 레코드에서이 데이터셋의 레코드를 업데이트합니다.
  • 지정된 데이터셋의 레코드에 해당하는 레코드가이 데이터셋에 없는 경우는 지정된 데이터셋의 레코드가 새 레코드로이 데이터셋에 추가됩니다.
  • 해당 레코드가 삭제 된 레코드가 있으면 그것을 삭제합니다.

아니오

TFDMergeMetaMode

데이터셋 메타데이터 병합하는 방법 지정

모드설명
mmNone메타 데이터의 비교 및​​ 병합을하지 않습니다.
mmMerge

지정된 데이터 집합에서 열 이름을 검색하여 이름이 같은 열이 데이터셋에서 찾습니다. 그 후 다음 중 하나를 수행합니다.

  • 지정된 데이터셋의 메타 데이터에서이 데이터셋의 열의 데이터 형식과 크기를 업데이트합니다 (같은 이름의 열만).
  • 같은 이름의 열이 데이터셋에서 찾을 수없는 경우 새 열을 데이터셋에 추가합니다.
mmAdd

지정된 데이터 집합에서 열 이름을 검색하여 이름이 같은 열이 데이터셋에서 찾습니다. 같은 이름의 열이 데이터셋에서 찾을 수없는 경우 새 열을 데이터셋에 추가합니다.

mmUpdate

지정된 데이터 집합에서 열 이름을 검색하여 이름이 같은 열이 데이터셋에서 찾습니다. 같은 이름의 열이 데이터셋에서 발견 된 경우 해당 열의 데이터 형식과 크기를 지정된 데이터셋의 메타 데이터로 업데이트합니다.

mmAddOrError

이 데이터셋의 메타 데이터를 다음과 같이 업데이트합니다.

  • 이 데이터셋에 열이없는 경우는 mmAdd 모드를 적용합니다.
  • 그렇지 않으면 mmError 모드를 적용합니다.
mmError

지정된 데이터 집합에서 열 이름을 검색하여 이름이 같은 열이 데이터셋에서 찾습니다. 동명의 열이 없거나, 동명의 열 데이터 형식이나 크기가 일치하지 않는 경우는 예외를 전달합니다.

TFDDataSet.MergeDataSet 데모


해당 데모는 왼쪽에 표시되는 3개 데이터셋(memList, memList2, memDetail)을 병합해 오른쪽에 표시되는 데이터셋(memMerge)으로 병합합니다.

병합할 대상 데이터는 같은 구조(ID, Name)의 데이터셋 2개와 확장된 구조(ID, Name, addr)를 데이터셋을 병합합니다.


작성하며 주의할 점은, 

  1. 병합해 넣을 데이터셋(memMerge)에 기본키가 설정되어 있어야 합니다. => 아래 코드에서 "memMerge.Table.PrimaryKey := memDetail.Table.PrimaryKey;"
  2. 필드 종류가 다른 데이터셋(memDetail)을 병합할 경우, 병합할 데이터셋(memMerge)에 데이터가 있을 경우 메타데이터를 변경할 경우(mmMerge) 코드 내부에서 데이터셋 메타데이터(필드 정보)를 재 생성 함. 이때 기본키가 설정되지 않아 위 1번 오류 발생 -> 미리 필드를 생성 후 mmMerge 호출하지 말 것(필드 종류가 다를 경우에 한함)

procedure TForm1.Button1Click(Sender: TObject);
begin
  // 필드 추가
  memList.FieldDefs.Add('ID', ftInteger, 0, False);
  memList.FieldDefs.Add('Name', ftString, 20, False);
  memList.CreateDataSet;

  memList2.FieldDefs.Add('ID', ftInteger, 0, False);
  memList2.FieldDefs.Add('Name', ftString, 20, False);
  memList2.CreateDataSet;

  memDetail.FieldDefs.Add('ID', ftInteger, 0, False);
  memDetail.FieldDefs.Add('Name', ftString, 20, False);
  memDetail.FieldDefs.Add('addr', ftString, 50, False);
  memDetail.CreateDataSet;

  // 데이터 추가
  memList.Open;
  memList.AppendRecord([1, '김현수']);
  memList.AppendRecord([2, '홍길동']);
  memList.AppendRecord([3, '유관순']);

  memList2.Open;
  memList2.AppendRecord([4, '김원경']);
  memList2.AppendRecord([5, '박범용']);

  memDetail.Open;
  memDetail.AppendRecord([1, '김현수', '인천']);

  // Field 복사: 미리 복사하지 않으면 Detail 머지 시 PK 설정되지 않음
  memMerge.MergeDataSet(memDetail, dmNone, mmMerge);
  // 병합해 넣을 데이터셋(memMerge)에 기본키가 설정되어 있어야 함. 기본키가 없으면 'no destination key defined' 오류 발생
  memMerge.Table.PrimaryKey := memDetail.Table.PrimaryKey;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  memMerge.MergeDataSet(memList, dmDataMerge, mmNone);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  memMerge.MergeDataSet(memList2, dmDataMerge, mmNone);
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  memMerge.MergeDataSet(memDetail, dmDataMerge, mmNone);
end;

참고