2つのテーブルを1つのテーブルにレプリケーションす場合には以下のような手順で実施します。
1.一つのターゲットテーブルに対して、各ソーステーブルからレプリケーションを作成します。
2.ターゲットテーブルでのトランケートや結合を制御するため、各レプリケーションでスクリプトを設定します。
3.レプリケーションを一つのグループに設定します。
4.全てのレコードを削除し、ターゲットテーブルをクリーンアップします。
5.レプリケーションを実行します。
例として、以下のようなレプリケーションを行う場合をご紹介します。
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にその情報は連携されない
等々
そのため、連携を行うテーブルに合わせてスクリプトをカスタマイズする必要があります。
関連したトピックス
- Syniti Data Replication (旧DBMoto)でのスクリプトの書き方④:レプリケーションスクリプト
- [Syniti(DBMoto)][スクリプト] 特定カラムの値が変更となった場合、ターゲットのレコードを削除するサンプルスクリプト
- [DBMoto][スクリプト]条件付きレプリケーションを行うサンプルVBスクリプト
- [DBMoto]「未マッピング使用」機能によるマッピング外のデータを活用したレプリケーション
- 外部DLL(COM)の使用方法【リアルタイムレプリケーションツールDBMoto】
- ミラーリングおいてのレコード数を確認の方法【リアルタイムレプリケーションツールDBMoto】
- Syniti Data Replication (旧DBMoto)でのスクリプトの書き方③:グローバルスクリプト用の関数とイベント
- 複数のテーブルにあるレコードを1つのテーブルへ統合する際の注意点【リアルタイムレプリケーションツールDBMoto】
- レプリケーションの際にnullを特定の値に変換する方法 その2【リアルタイムレプリケーションツールDBMoto】
- [DBMoto]関数を使用してレプリケーション時のデータを変換する方法(VB/C#言語選択、関数適用、ユーザ関数作成、置換関数、一括設定手順)