如何:定義合併資料表發行項之間的邏輯記錄關聯性 (複寫 Transact-SQL 程式設計)

[!附註]

未來的 Microsoft SQL Server 版本將移除這項功能。請避免在新的開發工作中使用這項功能,並規劃修改目前使用這項功能的應用程式。

合併式複寫可讓您在不同資料表內定義相關資料列之間的關聯性。這表示在同步處理期間,資料列可以當做交易式單位來處理。可以在兩個發行項之間定義邏輯記錄,不論這些發行項是否有聯結篩選關聯性。如需詳細資訊,請參閱<使用邏輯記錄分組相關資料列的變更>。您可以使用複寫預存程序,以程式設計方式指定發行項之間的邏輯記錄關聯性。

定義沒有相關聯結篩選的邏輯記錄關聯性

  1. 如果發行集包含任何篩選的發行項,請執行 sp_helpmergepublication,並記下結果集中的 use_partition_groups 值。

    • 如果這個值是 1,則表示已經使用預先計算的資料分割。

    • 如果這個值是 0,請在發行集資料庫的發行者上執行 sp_changemergepublication。請為 **@property** 指定 use_partition_groups 的值,並為 **@value** 指定 true 的值。

      [!附註]

      如果發行集不支援預先計算的資料分割,將無法使用邏輯記錄。如需詳細資訊,請參閱<使用預先計算的資料分割最佳化參數化篩選效能>主題中的「使用預先計算的資料分割之需求」。

    • 如果此值為 NULL,則必須執行快照集代理程式,才能為發行集產生初始快照集。

  2. 如果組成此邏輯記錄的發行項不存在,請在發行集資料庫的發行者上執行 sp_addmergearticle。針對此邏輯記錄指定下列其中一個衝突偵測和解決選項:

    • 若要偵測及解決邏輯記錄中相關資料列內所發生的衝突,請為 **@logical_record_level_conflict_detection** 和 **@logical_record_level_conflict_resolution** 指定 true 的值。

    • 若要使用標準資料列層級或資料行層級的衝突偵測與解決方法,請為 **@logical_record_level_conflict_detection** 和 **@logical_record_level_conflict_resolution** 指定 false 的值 (這是預設值)。

  3. 針對組成此邏輯記錄的每一個發行項重複步驟 2。您必須針對此邏輯記錄中的每一個發行項使用相同的衝突偵測和解決選項。如需詳細資訊,請參閱<偵測和解決邏輯記錄中的衝突>。

  4. 在發行集資料庫的發行者上,執行 sp_addmergefilter。指定 @publication**、關聯性中 @article** 的一個發行項名稱、@join_articlename** 的第二個發行項名稱、@filtername** 的關聯性名稱、為 @join_filterclause** 定義兩個發行項之間之關聯性的子句、@join_unique_key** 的聯結類型,以及 **@filter_type** 的下列其中一個值:

    • 2 - 定義邏輯關聯性。

    • 3 - 定義具有聯結篩選的邏輯關聯性。

    [!附註]

    如果未使用聯結篩選,則兩個發行項之間的關聯性方向就不是那麼重要。

  5. 針對發行集中每一個剩餘的邏輯記錄關聯性重複步驟 2。

變更邏輯記錄的衝突偵測和解決方式

  1. 若要偵測及解決邏輯記錄中相關資料列內所發生的衝突:

    • 在發行集資料庫的發行者上,執行 sp_changemergearticle。請為 **@property** 指定 logical_record_level_conflict_detection 的值,並為 **@value** 指定 true 的值。為 **@force_invalidate_snapshot** 和 **@force_reinit_subscription** 指定 1 的值。

    • 在發行集資料庫的發行者上,執行 sp_changemergearticle。請為 **@property** 指定 logical_record_level_conflict_resolution 的值,並為 **@value** 指定 true 的值。為 **@force_invalidate_snapshot** 和 **@force_reinit_subscription** 指定 1 的值。

  2. 若要使用標準資料列層級或資料行層級的衝突偵測與解決方式:

    • 在發行集資料庫的發行者上,執行 sp_changemergearticle。請為 **@property** 指定 logical_record_level_conflict_detection 的值,並為 **@value** 指定 false 的值。為 **@force_invalidate_snapshot** 和 **@force_reinit_subscription** 指定 1 的值。

    • 在發行集資料庫的發行者上,執行 sp_changemergearticle。請為 **@property** 指定 logical_record_level_conflict_resolution 的值,並為 **@value** 指定 false 的值。為 **@force_invalidate_snapshot** 和 **@force_reinit_subscription** 指定 1 的值。

移除邏輯記錄關聯性

  1. 在發行集資料庫的發行者上,執行下列查詢來傳回有關針對指定之發行集定義之所有邏輯記錄關聯性的資訊:

    SELECT f.* FROM sysmergesubsetfilters AS f 
    INNER JOIN sysmergepublications AS p
    ON f.pubid = p.pubid WHERE p.[name] = @publication;
    

    請注意從結果集中 filtername 資料行所移除的邏輯記錄關聯性名稱。

    [!附註]

    此查詢會傳回與 sp_helpmergefilter 相同的資訊,但是此系統預存程序只會傳回也屬於聯結篩選之邏輯記錄關聯性的相關資訊。

  2. 在發行集資料庫的發行者上,執行 sp_dropmergefilter。指定 **@publication**、關聯性中 **@article** 的其中一個發行項名稱,以及步驟 1 中 **@filtername** 的關聯性名稱。

範例

這個範例會在現有的發行集上啟用預先計算的資料分割,並針對 SalesOrderHeader 和 SalesOrderDetail 資料表建立組成兩個新發行項的邏輯記錄。

-- Remove ON DELETE CASCADE from FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID;
-- logical records cannot be used with ON DELETE CASCADE. 
IF EXISTS (SELECT * FROM sys.objects 
WHERE name = 'FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID')
BEGIN
    ALTER TABLE [Sales].[SalesOrderDetail] 
    DROP CONSTRAINT [FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID] 
END

ALTER TABLE [Sales].[SalesOrderDetail]  
WITH CHECK ADD CONSTRAINT [FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID] 
FOREIGN KEY([SalesOrderID])
REFERENCES [Sales].[SalesOrderHeader] ([SalesOrderID])
GO

DECLARE @publication    AS sysname;
DECLARE @table1 AS sysname;
DECLARE @table2 AS sysname;
DECLARE @table3 AS sysname;
DECLARE @salesschema AS sysname;
DECLARE @hrschema AS sysname;
DECLARE @filterclause AS nvarchar(1000);
DECLARE @partitionoption AS bit;
SET @publication = N'AdvWorksSalesOrdersMerge'; 
SET @table1 = N'SalesOrderDetail'; 
SET @table2 = N'SalesOrderHeader'; 
SET @salesschema = N'Sales';
SET @hrschema = N'HumanResources';
SET @filterclause = N'Employee.LoginID = HOST_NAME()';

-- Ensure that the publication uses precomputed partitions.
SET @partitionoption = (SELECT [use_partition_groups] FROM sysmergepublications 
    WHERE [name] = @publication);
IF @partitionoption <> 1
BEGIN
    EXEC sp_changemergepublication 
        @publication = @publication, 
        @property = N'use_partition_groups', 
        @value = 'true',
        @force_invalidate_snapshot = 1;
END  

-- Add a filtered article for the Employee table.
EXEC sp_addmergearticle 
  @publication = @publication, 
  @article = @table1, 
  @source_object = @table1, 
  @type = N'table', 
  @source_owner = @hrschema,
  @schema_option = 0x0004CF1,
  @description = N'article for the Employee table',
  @subset_filterclause = @filterclause;

-- Add an article for the SalesOrderHeader table.
EXEC sp_addmergearticle 
  @publication = @publication, 
  @article = @table2, 
  @source_object = @table2, 
  @type = N'table', 
  @source_owner = @salesschema,
  @schema_option = 0x0034EF1,
  @description = N'article for the SalesOrderHeader table';

-- Add an article for the SalesOrderDetail table.
EXEC sp_addmergearticle 
  @publication = @publication, 
  @article = @table3, 
  @source_object = @table3, 
  @source_owner = @salesschema,
  @description = 'article for the SalesOrderDetail table', 
  @identityrangemanagementoption = N'auto', 
  @pub_identity_range = 100000, 
  @identity_range = 100, 
  @threshold = 80;

-- Add a merge join filter between Employee and SalesOrderHeader.
EXEC sp_addmergefilter 
  @publication = @publication, 
  @article = @table2, 
  @filtername = N'SalesOrderHeader_Employee', 
  @join_articlename = @table1, 
  @join_filterclause = N'Employee.BusinessEntityID = SalesOrderHeader.SalesPersonID', 
  @join_unique_key = 1, 
  @filter_type = 1, 
  @force_invalidate_snapshot = 1, 
  @force_reinit_subscription = 1;

-- Create a logical record relationship that is also a merge join 
-- filter between SalesOrderHeader and SalesOrderDetail.
EXEC sp_addmergefilter 
  @publication = @publication, 
  @article = @table3, 
  @filtername = N'LogicalRecord_SalesOrderHeader_SalesOrderDetail', 
  @join_articlename = @table2, 
  @join_filterclause = N'[SalesOrderHeader].[SalesOrderID] = [SalesOrderDetail].[SalesOrderID]', 
  @join_unique_key = 1, 
  @filter_type = 3, 
  @force_invalidate_snapshot = 1, 
  @force_reinit_subscription = 1;
GO