2つのソーステーブルからターゲットの一つのレコードにレプリケーション


2つのテーブルを1つのテーブルにレプリケーションす場合には以下のような手順で実施します。
1.一つのターゲットテーブルに対して、各ソーステーブルからレプリケーションを作成します。
2.ターゲットテーブルでのトランケートや結合を制御するため、各レプリケーションでスクリプトを設定します。
3.レプリケーションを一つのグループに設定します。
4.全てのレコードを削除し、ターゲットテーブルをクリーンアップします。
5.レプリケーションを実行します。

画像1テーブル1
画像2マッピング
画像3スクリプト

例として、以下のようなレプリケーションを行う場合をご紹介します。

MULTITEST1 > MULTITEST3のレプリケーションを作成します。
1.マッピング設定でID, NAME, COMPANYをマッピングします。
2.UNITにはvbNullをマップします。

3.レプリケーションを無効にし、ウィザードを完了します。
4.レプリケーションのプロパティを開きます。
5.スクリプトの使用にチェックを入れ、以下のスクリプトを追加します。

Imports Microsoft.VisualBasic
Imports DBMotoPublic
Imports DBMotoScript
Imports DBRS.GlobalScript

Namespace DBRS
    Public Class ReplicationScript : Inherits IreplicationScript
      Dim PrimaryKey As String
      Dim Field As String
      Dim Table2 As String 

      Public Overrides Sub Refresh_onBeforeTruncate(ByRef CancelTruncate As Boolean, ByRef Filter As String)
    'リフレッシュ時のレコード削除を無効化
        CancelTruncate = True
      End Sub

      Public Overrides Sub Record_onAfterMapping( recSource As DBMotoPublic.IRecord,  recTarget As DBMotoPublic.IRecord, ByRef AbortRecord As Boolean, ByRef DisableReplication As Boolean)
        Table2 = """asami"".MULTITEST2" 'もう一方のテーブル
        PrimaryKey = "ID" '主キー
        Field = "UNIT" 'vbNullをマップしたフィールド
        '主キーが変更されていない場合
        If recTarget.GetValueAfter(PrimaryKey) = Nothing Then
          recTarget.SetValueAfter(Field, Nothing)
        '主キーが変更されている場合(またはinsert)
        Else
          InterpolationFields (recTarget)
        End If
      End Sub
      '補間するためにFieldの値を検索
      Private Sub InterpolationFields (recTarget As IRecord)
        Dim cmd As System.Data.IdbCommand
        Dim rs As System.Data.IdataReader
        Dim SQL As String
        'Table2からPrimaryKeyのレコードを検索
        SQL = "Select * From " + Table2 + " Where " + PrimaryKey + " = " & recTarget.GetValueAfter(PrimaryKey)
        'レプリケーションのソース接続情報を取得
        cmd = SourceConnection.CreateCommand
        'コマンドにSQLクエリを代入
        cmd.CommandText = SQL
        'SQLを実行
        rs = cmd.ExecuteReader
        'FieldのvbNullを取得した値に置き換え
        While rs.Read
          recTarget.SetValueAfter(Field, rs(Field))
        End While
        rs.Close
      End Sub
    End Class
End Namespace

MULTITEST2 > MULTITEST3のレプリケーションを作成します。
1.マッピング設定でID, NAME, UNITをマッピングします。
2.COMPANYにはvbNullをマップします。
3.レプリケーションを無効にし、ウィザードを完了します。
4.レプリケーションのプロパティを開きます。
5.スクリプトの使用にチェックを入れ、以下のスクリプトを追加します。

Imports Microsoft.VisualBasic
Imports DBMotoPublic
Imports DBMotoScript
Imports DBRS.GlobalScript

Namespace DBRS
    Public Class ReplicationScript : Inherits IreplicationScript
      Dim PrimaryKey As String
      Dim Field As String
      Dim Table1 As String
      Dim Table2 As String
      Dim Table3 As String 

      Public Overrides Sub Refresh_onBeforeTruncate(ByRef CancelTruncate As Boolean, ByRef Filter As String)
            CancelTruncate = True
      End Sub

      Public Overrides Sub Record_onAfterMapping( recSource As DBMotoPublic.IRecord,  recTarget As DBMotoPublic.IRecord, ByRef AbortRecord As Boolean, ByRef DisableReplication As Boolean)
        Table1 = """asami"".MULTITEST1" 'もう一方のソーステーブル
        Table2 = """asami"".MULTITEST2" 'ソーステーブル
        Table3 = "ASAMI.MULTITEST3" 'ターゲットテーブル
        PrimaryKey = "ID" '主キー
        Field = "UNIT" 'もう一方のレプリケーションでvbNullをマップしたフィールド
        'insert,update,deleteでの場合分け
        Select Case recTarget.OperationType
          'insertの場合、ターゲットのFieldに対してupdateを実施
          Case enmOperationType.Insert
            UpdateFields(recTarget)
            AbortRecord = True
          'updateの場合
          Case enmOperationType.Update
            '主キーが変更されている場合、ターゲットの変更前のFieldをNullにupdate
            If recTarget.GetValueAfter(PrimaryKey) <> recTarget.GetValueBefore(PrimaryKey) Then
              SetNull(recTarget)
            End If
            'ターゲットのFieldに対してupdateを実施
            UpdateFields(recTarget)
            AbortRecord = True
            'Deleteの場合
            Case enmOperationType.Delete
        'Fieldをnullにupdate
              SetNull(recTarget)
              AbortRecord = True
        End Select
      End Sub

      'Fieldに対するupdate
      Private Sub UpdateFields (recTarget As IRecord)
        Dim SQL As String
        SQL = "Update " + Table3 + " Set "
        'FieldがNullの場合はNullにupdate
        If recTarget.GetValueAfter(Field) = Nothing Then
          SQL = SQL + " " + Field + " = Null "
        'Fieldの値でupdateを実施
        Else
          SQL = SQL + " " + Field + " = '" + recTarget.GetValueAfter(Field) + "'"
        End If
        '主キーに変更がない場合は変更前の主キーのレコードをupdate
        if recTarget.GetValueAfter("ID") = Nothing then
          SQL = SQL + " Where " + PrimaryKey + " = '" + recTarget.GetValueBefore(PrimaryKey) +  "'"
        '主キーが変更されている場合は変更後の主キーのレコードをupdate
        else
          SQL = SQL + " Where " + PrimaryKey + " = '" + recTarget.GetValueAfter(PrimaryKey) +  "'"
        End if 

        AddLog ("UpdateFields SQL: " + SQL, 0)
        Try
          Dim cmd As System.Data.IdbCommand
          cmd = TargetConnection.CreateCommand
          cmd.CommandText = SQL
          cmd.ExecuteNonQuery()
        Catch Ex As System.Exception
          AddLog (Table2 + ".*_onAfterFieldMapping (UpdateFields): Cannot update field UNIT on Table " + Table3 + " (" + Ex.Message + ")", 1)
        End Try
      End Sub
      'FieldをNullにupdate
      Private Sub SetNull (recTarget As IRecord)
        Dim SQL As String

        SQL = "Update " + Table3 + " Set " + Field + " = Null Where ID = '" + recTarget.GetValueBefore(PrimaryKey) +  "'"
        AddLog ("SetNull: " + SQL, 0)
        Try
            Dim cmd As System.Data.IdbCommand
            cmd = TargetConnection.CreateCommand
            cmd.CommandText = SQL
            cmd.ExecuteNonQuery()
        Catch Ex As System.Exception
            AddLog (Table2 + ".*_onAfterFieldMapping (SetNull): Cannot update field UNIT on Table " + Table3 + " (" + Ex.Message + ")", 1)
        End Try
      End Sub
    End Class
End Namespace

このようにスクリプトを使用することでターゲットテーブルの一つのレコードを2つのソーステーブルから作成可能です。
しかし、このスクリプトには以下のような制限もあります。
・リフレッシュ時には手動でのターゲットテーブルのレコード削除が必須
・MULTITEST1に存在しない主キーをMULTITEST2にinsertした場合、MULTITEST3にその情報は連携されない
等々

そのため、連携を行うテーブルに合わせてスクリプトをカスタマイズする必要があります。

関連したトピックス

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください