Definir una relación de registros lógicos entre artículos de tabla de mezcla

Se aplica a:SQL Server

En este tema se describe cómo definir una relación de registros lógicos entre los artículos de tabla de combinación en SQL Server mediante SQL Server Management Studio, Transact-SQL o Replication Management Objects (RMO).

La replicación de mezcla le permite definir una relación entre filas relacionadas de tablas diferentes. De ese modo, las filas se pueden procesar como una unidad transaccional durante la sincronización. Se puede definir un registro lógico entre dos artículos independientemente de que tengan una relación de filtro de unión o no. Para más información, vea Agrupar cambios en filas relacionadas con registros lógicos.

Nota:

Esta característica se quitará en una versión futura de SQL Server. Evite utilizar esta característica en nuevos trabajos de desarrollo y tenga previsto modificar las aplicaciones que actualmente la utilizan.

En este tema

Antes de empezar

Limitaciones y restricciones

  • Si agrega, modifica o elimina un registro lógico una vez inicializadas las suscripciones a la publicación, deberá generar una instantánea nueva y reinicializar todas las suscripciones después de realizar el cambio. Para obtener más información sobre los requisitos para los cambios de propiedad, consulte Cambiar las propiedades de la publicación y de los artículos (Cambiar las propiedades de la publicación y de los artículos).

Uso de SQL Server Management Studio

Defina registros lógicos en el cuadro de diálogo Agregar combinación, que está disponible en el Asistente para nueva publicación y en el cuadro de diálogo Propiedades de la publicación: <Publicación>. Para obtener más información sobre el uso del asistente y el acceso al cuadro de diálogo, consulte Create a Publication (Crear una publicación) y Ver y modificar propiedades de publicación.

Los registros lógicos se pueden definir en el cuadro de diálogo Agregar combinación solamente si se aplican a un filtro de combinación en una publicación de combinación y la publicación cumple los requisitos para utilizar particiones precalculadas. Debe utilizar procedimientos almacenados para definir registros lógicos que no se aplican a los filtros de combinación y para establecer la detección y resolución de conflictos en el nivel de registro lógico.

Para definir una relación de registros lógicos

  1. En la página Filtrar filas de tabla del Asistente para nueva publicación o la página Filtrar filas del cuadro de diálogo Propiedades de la publicación: <Publicación>, seleccione un filtro de fila en el panel Tablas filtradas.

    Una relación de registros lógicos está asociada con un filtro de combinación, que amplía un filtro de fila. Por tanto, debe definir un filtro de fila antes de poder ampliar el filtro con una combinación y aplicar una relación de registros lógicos. Una vez definido el filtro de combinación, podrá ampliarlo con otro filtro de combinación. Para obtener más información acerca de cómo definir filtros de combinación, vea Definir y modificar un filtro de combinación entre artículos de mezcla.

  2. Haga clic en Agregary, a continuación, en Agregar combinación para ampliar el filtro seleccionado.

  3. Defina el filtro de combinación en el cuadro de diálogo Agregar combinación y, a continuación, active la casilla Registro lógico.

  4. Si se encuentra en el cuadro de diálogo Propiedades de la publicación: <Publicación>, haga clic en Aceptar para guardar y cerrar el cuadro de diálogo.

Para eliminar una relación de registros lógicos

  • Elimine solamente la relación de registros lógicos o elimine la relación de registros lógicos y el filtro de combinación asociado a la misma.

    Para eliminar solamente la relación de registros lógicos:

    1. En la página Filtrar filas del Asistente para nueva publicación o en la página Filtrar filas del cuadro de diálogo Propiedades de la publicación: <Publicación>, seleccione el filtro de combinación asociado con la relación de registros lógicos del panel Tablas filtradas y, a continuación, haga clic en Editar.

    2. En el cuadro de diálogo Editar combinación , desactive la casilla Registro lógico.

    3. Seleccione Aceptar.

    Para eliminar la relación de registros lógicos y el filtro de combinación asociado a la misma:

    • En la página Filtrar filas del Asistente para nueva publicación o en el cuadro de diálogo Propiedades de la publicación: <Publicación>, seleccione un filtro en el panel Tablas filtradas y haga clic en Eliminar. Si el filtro de combinación que elimina está a su vez ampliado por otras combinaciones, esas combinaciones también se eliminarán.

Usar Transact-SQL

Puede especificar mediante programación las relaciones de registros lógicos entre los artículos usando procedimientos almacenados de replicación.

Para definir una relación de registros lógicos sin un filtro de combinación asociado

  1. Si la publicación contiene cualquier artículo que se filtra, ejecute sp_helpmergepublicationy tenga en cuenta el valor de use_partition_groups en el conjunto de resultados.

    • Si el valor es 1, las particiones precalculadas ya se están usando.

    • Si el valor es 0, ejecute sp_changemergepublication en el Publicador de la base de datos de publicación. Especifique un valor de use_partition_groups para @property y un valor de true para @value.

      Nota:

      Si la publicación no admite las particiones precalculadas, no se pueden usar registros lógicos. Para obtener más información, vea la sección Requisitos para utilizar particiones precalculadas de Optimizar el rendimiento de los filtros con parámetros con particiones calculadas previamente.

    • Si el valor es NULL, el Agente de instantáneas tiene que seguir ejecutándose para generar la instantánea inicial para la publicación.

  2. Si no existen los artículos que comprenderán el registro lógico, ejecute sp_addmergearticle en el Publicador de la base de datos de publicación. Especifique una de las siguientes opciones de detección y resolución de conflictos para el registro lógico:

    • Para detectar y solucionar conflictos que se producen dentro de las filas relacionadas en el registro lógico, especifique un valor de true para @logical_record_level_conflict_detection y @logical_record_level_conflict_resolution.

    • Para usar la resolución y detección de conflictos en el nivel de filas o columnas, especifique un valor de false para @logical_record_level_conflict_detection y @logical_record_level_conflict_resolution, que es el valor predeterminado.

  3. Repita el paso 2 para cada artículo que comprenderá el registro lógico. Debe usar la misma opción de detección y resolución de conflictos para cada artículo del registro lógico. Para más información, consulte Detectar y solucionar conflictos en registros lógicos.

  4. En la base de datos de publicación del publicador, ejecute sp_addmergefilter. Especifique @publication, el nombre de un artículo en la relación para @article, el nombre del segundo artículo para @join_articlename, un nombre para la relación para @filtername, una cláusula que define la relación entre los dos artículos para @join_filterclause, el tipo de combinación para @join_unique_key y uno de los valores siguientes para @filter_type:

    • 2 : define una relación lógica.

    • 3 : define una relación lógica con un filtro de combinación.

    Nota:

    Si no se usa un filtro de combinación, la dirección de la relación entre los dos artículos no es importante.

  5. Repita el paso 2 para cada una de las demás relaciones de registros lógicos de la publicación.

Para cambiar la detección y resolución de conflictos para los registros lógicos

  1. Para detectar y solucionar conflictos que se producen dentro de las filas relacionadas en el registro lógico:

    • En la base de datos de publicación del publicador, ejecute sp_changemergearticle. Especifique un valor de logical_record_level_conflict_detection para @property y un valor de true para @value. Especifique un valor de 1 para @force_invalidate_snapshot y @force_reinit_subscription.

    • En la base de datos de publicación del publicador, ejecute sp_changemergearticle. Especifique un valor de logical_record_level_conflict_resolution para @property y un valor de true para @value. Especifique un valor de 1 para @force_invalidate_snapshot y @force_reinit_subscription.

  2. Para usar la detección y resolución de conflictos de nivel de columna y de fila estándar:

    • En la base de datos de publicación del publicador, ejecute sp_changemergearticle. Especifique un valor de logical_record_level_conflict_detection para @property y un valor de false para @value. Especifique un valor de 1 para @force_invalidate_snapshot y @force_reinit_subscription.

    • En la base de datos de publicación del publicador, ejecute sp_changemergearticle. Especifique un valor de logical_record_level_conflict_resolution para @property y un valor de false para @value. Especifique un valor de 1 para @force_invalidate_snapshot y @force_reinit_subscription.

Para quitar una relación de registros lógicos

  1. En el Publicador de la base de datos de publicación, ejecute la consulta siguiente para devolver información sobre todas las relaciones de registros lógicos definidas para la publicación especificada:

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

    Tenga en cuenta el nombre de la relación de registros lógicos que se está quitando en la columna filtername del conjunto de resultados.

    Nota:

    Esta consulta devuelve la misma información que sp_helpmergefilter; sin embargo, este procedimiento almacenado del sistema solamente devuelve información sobre las relaciones de registros lógicos que también son filtros de combinación.

  2. En la base de datos de publicación del publicador, ejecute sp_dropmergefilter. Especifique @publication, el nombre de uno de los artículos en la relación para @articley el nombre de la relación del paso 1 para @filtername.

Ejemplo (Transact-SQL)

En este ejemplo se habilitan las particiones calculadas previamente en una publicación existente y se crea un registro lógico que comprende los dos artículos nuevos para las tablas SalesOrderHeader y 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.EmployeeID = 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

Usar Replication Management Objects (RMO)

Nota:

La replicación de mezcla le permite especificar que se realice un seguimiento de los conflictos y se resuelvan en el nivel de registro lógico, pero dichas opciones no se pueden establecer usando RMO.

Para definir una relación de registros lógicos sin un filtro de combinación asociado

  1. Cree una conexión al publicador mediante la clase ServerConnection .

  2. Cree una instancia de la clase MergePublication , establezca las propiedades Name y DatabaseName para la publicación y establezca la propiedad ConnectionContext en la conexión creada en el paso 1.

  3. Llame al método LoadProperties para obtener las propiedades del objeto. Si este método devuelve false, significa que las propiedades de publicación del paso 2 se definieron incorrectamente, o bien que la publicación no existe.

  4. Si la propiedad PartitionGroupsOption está establecida en False, cámbiela a True.

  5. Si los artículos que van a componer el registro lógico no existen, cree una instancia de la clase MergeArticle y establezca las propiedades siguientes:

    • El nombre del artículo para Name.

    • El nombre de la publicación para PublicationName.

    • (Opcional) Si se filtra el artículo horizontalmente, especifique la cláusula de filtro de filas para la propiedad FilterClause . Utilice esta propiedad para especificar un filtro de fila estático o con parámetros. Para obtener más información, consulte Filtros de fila con parámetros.

    Para más información, consulte Define an Article.

  6. Llame al método Create.

  7. Repita los pasos 5 y 6 para cada artículo que comprende el registro lógico.

  8. Cree una instancia de la clase MergeJoinFilter para definir la relación de registros lógicos entre los artículos. A continuación, establezca las siguientes propiedades:

  9. Llame al método AddMergeJoinFilter en el objeto que representa el artículo secundario en la relación. Pase el objeto MergeJoinFilter del paso 8 para definir la relación.

  10. Repita los pasos 8 y 9 para cada una de las demás relaciones de registros lógicos de la publicación.

Ejemplo (RMO)

En este ejemplo se crea un registro lógico que incluye los dos artículos nuevos para las tablas SalesOrderHeader y SalesOrderDetail .

           // Define the Publisher and publication names.
           string publisherName = publisherInstance;
           string publicationName = "AdvWorksSalesOrdersMerge";
           string publicationDbName = "AdventureWorks2022";

           // Specify article names.
           string articleName1 = "SalesOrderHeader";
           string articleName2 = "SalesOrderDetail";
           
           // Specify logical record information.
           string lrName = "SalesOrderHeader_SalesOrderDetail";
           string lrClause = "[SalesOrderHeader].[SalesOrderID] = "
               + "[SalesOrderDetail].[SalesOrderID]";

           string schema = "Sales";

           MergeArticle article1 = new MergeArticle();
           MergeArticle article2 = new MergeArticle();
           MergeJoinFilter lr = new MergeJoinFilter();
           MergePublication publication = new MergePublication();

           // Create a connection to the Publisher.
           ServerConnection conn = new ServerConnection(publisherName);

           try
           {
               // Connect to the Publisher.
               conn.Connect();

               // Verify that the publication uses precomputed partitions.
               publication.Name = publicationName;
               publication.DatabaseName = publicationDbName;
               publication.ConnectionContext = conn;

               // If we can't get the properties for this merge publication, then throw an application exception.
               if (publication.LoadProperties())
               {
                   // If precomputed partitions is disabled, enable it.
                   if (publication.PartitionGroupsOption == PartitionGroupsOption.False)
                   {
                       publication.PartitionGroupsOption = PartitionGroupsOption.True;
                   }
               }
               else
               {
                   throw new ApplicationException(String.Format(
                       "Settings could not be retrieved for the publication. " +
                       "Ensure that the publication {0} exists on {1}.",
                       publicationName, publisherName));
               }

               // Set the required properties for the PurchaseOrderHeader article.
               article1.ConnectionContext = conn;
               article1.Name = articleName1;
               article1.DatabaseName = publicationDbName;
               article1.SourceObjectName = articleName1;
               article1.SourceObjectOwner = schema;
               article1.PublicationName = publicationName;
               article1.Type = ArticleOptions.TableBased;

               // Set the required properties for the SalesOrderDetail article.
               article2.ConnectionContext = conn;
               article2.Name = articleName2;
               article2.DatabaseName = publicationDbName;
               article2.SourceObjectName = articleName2;
               article2.SourceObjectOwner = schema;
               article2.PublicationName = publicationName;
               article2.Type = ArticleOptions.TableBased;

               if (!article1.IsExistingObject) article1.Create();
               if (!article2.IsExistingObject) article2.Create();

               // Define a logical record relationship between 
               // PurchaseOrderHeader and PurchaseOrderDetail. 

               // Parent article.
               lr.JoinArticleName = articleName1;
               
               // Child article.
               lr.ArticleName = articleName2;
               lr.FilterName = lrName;
               lr.JoinUniqueKey = true;
               lr.FilterTypes = FilterTypes.LogicalRecordLink;
               lr.JoinFilterClause = lrClause;

               // Add the logical record definition to the parent article.
               article1.AddMergeJoinFilter(lr);
           }
           catch (Exception ex)
           {
               // Do error handling here and rollback the transaction.
               throw new ApplicationException(
                   "The filtered articles could not be created", ex);
           }
           finally
           {
               conn.Disconnect();
           }
' Define the Publisher and publication names.
Dim publisherName As String = publisherInstance
Dim publicationName As String = "AdvWorksSalesOrdersMerge"
Dim publicationDbName As String = "AdventureWorks2022"

' Specify article names.
Dim articleName1 As String = "SalesOrderHeader"
Dim articleName2 As String = "SalesOrderDetail"

' Specify logical record information.
Dim lrName As String = "SalesOrderHeader_SalesOrderDetail"
Dim lrClause As String = "[SalesOrderHeader].[SalesOrderID] = " _
        & "[SalesOrderDetail].[SalesOrderID]"

Dim schema As String = "Sales"

Dim article1 As MergeArticle = New MergeArticle()
Dim article2 As MergeArticle = New MergeArticle()
Dim lr As MergeJoinFilter = New MergeJoinFilter()
Dim publication As MergePublication = New MergePublication()

' Create a connection to the Publisher.
Dim conn As ServerConnection = New ServerConnection(publisherName)

Try
    ' Connect to the Publisher.
    conn.Connect()

    ' Verify that the publication uses precomputed partitions.
    publication.Name = publicationName
    publication.DatabaseName = publicationDbName
    publication.ConnectionContext = conn

    ' If we can't get the properties for this merge publication, then throw an application exception.
    If publication.LoadProperties() Then
        ' If precomputed partitions is disabled, enable it.
        If publication.PartitionGroupsOption = PartitionGroupsOption.False Then
            publication.PartitionGroupsOption = PartitionGroupsOption.True
        End If
    Else
        Throw New ApplicationException(String.Format( _
            "Settings could not be retrieved for the publication. " _
            & "Ensure that the publication {0} exists on {1}.", _
            publicationName, publisherName))
    End If

    ' Set the required properties for the SalesOrderHeader article.
    article1.ConnectionContext = conn
    article1.Name = articleName1
    article1.DatabaseName = publicationDbName
    article1.SourceObjectName = articleName1
    article1.SourceObjectOwner = schema
    article1.PublicationName = publicationName
    article1.Type = ArticleOptions.TableBased

    ' Set the required properties for the SalesOrderDetail article.
    article2.ConnectionContext = conn
    article2.Name = articleName2
    article2.DatabaseName = publicationDbName
    article2.SourceObjectName = articleName2
    article2.SourceObjectOwner = schema
    article2.PublicationName = publicationName
    article2.Type = ArticleOptions.TableBased

    If Not article1.IsExistingObject Then
        article1.Create()
    End If
    If Not article2.IsExistingObject Then
        article2.Create()
    End If

    ' Define a logical record relationship between 
    ' SalesOrderHeader and SalesOrderDetail. 

    ' Parent article.
    lr.JoinArticleName = articleName1
    ' Child article.
    lr.ArticleName = articleName2
    lr.FilterName = lrName
    lr.JoinUniqueKey = True
    lr.FilterTypes = FilterTypes.LogicalRecordLink
    lr.JoinFilterClause = lrClause

    ' Add the logical record definition to the parent article.
    article1.AddMergeJoinFilter(lr)
Catch ex As Exception
    ' Do error handling here and rollback the transaction.
    Throw New ApplicationException( _
            "The filtered articles could not be created", ex)
Finally
    conn.Disconnect()
End Try

Consulte también

Definir y modificar un filtro de combinación entre artículos de mezcla
Definir y modificar un filtro de fila con parámetros para un artículo de mezcla
Definir y modificar un filtro de fila estático
Agrupar cambios en filas relacionadas con registros lógicos
Optimizar el rendimiento de los filtros con parámetros con particiones calculadas previamente
Agrupar cambios en filas relacionadas con registros lógicos