none
Replicacion de datos SQL Mediante Procedimiento Almacenado RRS feed

  • Pregunta

  • Tengo dos bases de datos la primera seria bd1 y la segunda bd2

    En la bd1 tengo una tabla que se llama conceptos la cual contiene datos actualizados hasta la fecha, y la segunda también contiene una tabla llamada conceptos pero sus datos fueron actualizados hace algún tiempo, yo necesito mantener la bd2 actualizada en base a la bd1.

    Necesito hacer un Procedimiento almancenado para comprobar los registros que ya existen en la bd2 y en la bd1 para solo copiar los nuevos registros que se vallan agregando en la bd1, y también comprobar si un registro fue actualizado en la bd1 que se actualice en la bd2 también

    Nota: la tabla concepto de la bd2 no puede ser eliminada ya que tiene relaciones a otras tablas, ni es una opción ya que cuenta con muchísimos registros y seria un proceso muy largo para estarlos pasando todos, todos los días.

    Ejemplo de campos de la tabla

    IdCocepto       NombreConcepto FechaConcepto  Estado

    INT IDENTITY   VARCHAR(50)          DATE            BIT


     



    • Editado Adalberto88 sábado, 21 de septiembre de 2019 19:55
    sábado, 21 de septiembre de 2019 19:45

Respuestas

  • Me funciono perfecto su respuesta José Diz, solo una cosa más como puedo validar de igual manera, si un registro se elimino en la bd1 no se si pueda que se elimine en la bd2 también.

     

    -- código #1 v2
    set IDENTITY_INSERT bd2.schema_name.conceptos on;
    
    MERGE 
      into bd2.schema_name.conceptos with (holdlock) as T2
      using bd1.schema_name.conceptos as T1
      on T1.IdConcepto = T2.IdConcepto
      -- si un registro fue actualizado en la bd1 que se actualice en la bd2 también
      when matched and (T2.NombreConcepto <> T1.NombreConcepto
                        or T2.FechaConcepto <> T1.FechaConcepto
                        or T2.Estado <> T1.Estado)
           then UPDATE NombreConcepto= T1.NombreConcepto,
                       FechaConcepto= T1.FechaConcepto,
                       Estado= T1.Estado
      --  copiar los nuevos registros que se vallan agregando en la bd1
      when not matched by target 
           then INSERT (IdConcepto, NombreConcepto, FechaConcepto, Estado)
                      values (T1.IdConcepto, T1.NombreConcepto, T1.FechaConcepto, T1.Estado)
      -- si un registro se elimino en la bd1 que se elimine en la bd2 también
      when not matched by source
           then DELETE;
    
    set IDENTITY_INSERT bd2.schema_name.conceptos off;
     



    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Marcado como respuesta Adalberto88 domingo, 22 de septiembre de 2019 13:53
    • Editado José Diz jueves, 3 de octubre de 2019 9:22
    domingo, 22 de septiembre de 2019 11:31

Todas las respuestas

  • Necesito hacer un Procedimiento almancenado para comprobar los registros que ya existen en la bd2 y en la bd1 para solo copiar los nuevos registros que se vallan agregando en la bd1, y también comprobar si un registro fue actualizado en la bd1 que se actualice en la bd2 también

    ¿Cómo se prueba que una fila ha sido cambiada en bd1? ¿Sólo compare las fechas o necesita comparar columna por columna?

    ---

    He aquí una sugerencia que compara columna por columna:

    -- código #1
    set IDENTITY_INSERT bd2.schema_name.conceptos on;
    
    MERGE 
      into bd2.schema_name.conceptos with (holdlock) as T2
      using bd1.schema_name.conceptos as T1
      on T1.IdConcepto = T2.IdConcepto
      -- si un registro fue actualizado en la bd1 que se actualice en la bd2 también
    when matched and (T2.NombreConcepto <> T1.NombreConcepto or T2.FechaConcepto <> T1.FechaConcepto or T2.Estado <> T1.Estado) then UPDATE NombreConcepto= T1.NombreConcepto, FechaConcepto= T1.FechaConcepto, Estado= T1.Estado --  copiar los nuevos registros que se vallan agregando en la bd1
    when not matched by target then INSERT (IdConcepto, NombreConcepto, FechaConcepto, Estado) values (T1.IdConcepto, T1.NombreConcepto, T1.FechaConcepto, T1.Estado); set IDENTITY_INSERT bd2..conceptos off;
          

    ---

    Si las bases de datos están en diferentes instancias, o en diferentes computadoras, es necesario establecer la conexión con el servidor de antemano. Lectura sugerida: “Programação e otimização de consultas distribuídas”.

     


    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Editado José Diz jueves, 3 de octubre de 2019 9:22
    sábado, 21 de septiembre de 2019 21:18
  • Me funciono perfecto su respuesta José Diz, solo una cosa más como puedo validar de igual manera, si un registro se elimino en la bd1 no se si pueda que se elimine en la bd2 también.
    domingo, 22 de septiembre de 2019 0:45
  • Me funciono perfecto su respuesta José Diz, solo una cosa más como puedo validar de igual manera, si un registro se elimino en la bd1 no se si pueda que se elimine en la bd2 también.

     

    -- código #1 v2
    set IDENTITY_INSERT bd2.schema_name.conceptos on;
    
    MERGE 
      into bd2.schema_name.conceptos with (holdlock) as T2
      using bd1.schema_name.conceptos as T1
      on T1.IdConcepto = T2.IdConcepto
      -- si un registro fue actualizado en la bd1 que se actualice en la bd2 también
      when matched and (T2.NombreConcepto <> T1.NombreConcepto
                        or T2.FechaConcepto <> T1.FechaConcepto
                        or T2.Estado <> T1.Estado)
           then UPDATE NombreConcepto= T1.NombreConcepto,
                       FechaConcepto= T1.FechaConcepto,
                       Estado= T1.Estado
      --  copiar los nuevos registros que se vallan agregando en la bd1
      when not matched by target 
           then INSERT (IdConcepto, NombreConcepto, FechaConcepto, Estado)
                      values (T1.IdConcepto, T1.NombreConcepto, T1.FechaConcepto, T1.Estado)
      -- si un registro se elimino en la bd1 que se elimine en la bd2 también
      when not matched by source
           then DELETE;
    
    set IDENTITY_INSERT bd2.schema_name.conceptos off;
     



    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Marcado como respuesta Adalberto88 domingo, 22 de septiembre de 2019 13:53
    • Editado José Diz jueves, 3 de octubre de 2019 9:22
    domingo, 22 de septiembre de 2019 11:31
  • Justo lo que buscaba muchísimas Gracias José Diz!!
    domingo, 22 de septiembre de 2019 13:53
  • Una pregunta, no he probado el codigo pero no esto haria un barrido de toda la tabla siempre? y eso es bastante si la tabla o tablas son moderadamente grandes?

    Blog: www.sqlservertoolbox.blogspot.com.mx

    lunes, 23 de septiembre de 2019 18:35
  • Una pregunta, no he probado el codigo pero no esto haria un barrido de toda la tabla siempre? y eso es bastante si la tabla o tablas son moderadamente grandes?

    Enrique, en la documentación de la instrucción MERGE hay consejos sobre cómo optimizar el procesamiento:

    En el caso específico de este tema, se recomienda que en ambas tablas el índice primario sea la columna IdConcepto.

    Para comparar el rendimiento de diferentes soluciones para un mismo problema, se recomienda analizar los planes de ejecución: O Plano Perfeito.


    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Editado José Diz lunes, 23 de septiembre de 2019 20:01
    lunes, 23 de septiembre de 2019 19:54
  • Saludos Jose,

    Entiendo el punto y lo que dices simplemente hacia comentario que este codigo es bueno para una tabla pequeña a mediana sin muchos movimientos o con ejercucion talvez nocturna o una ventana, constante por inserción o cambio digamos como por un trigger seria algo malo a mi parecer, en todo caso gracias por tu respuesta.


    Blog: www.sqlservertoolbox.blogspot.com.mx

    lunes, 23 de septiembre de 2019 20:55
  • Enrique, lo que creo es que cualquier solución de código SQL que implique leer las dos tablas será ineficiente si no hay un índice de cobertura por la columna IdConcepto en ambas tablas.

    ---

    La solución ideal depende del análisis de dónde está cada base de datos, cuál es el tamaño de la DB1, cuál es el movimiento diario, etc.

    Por ejemplo, si las bases de datos están en diferentes ordenadores y la tabla CONCEPTOS tiene un alto número de fias, y con una conexión lenta entre los ordenadores, otra solución es crear un procedimiento de trigger que monitorice los cambios en la tabla CONCEPTOS de BD1, generando un fichero de comandos con instrucciones de tipo I, U y D, con la información necesaria para cada tipo de comando. Y en el ordenador donde se encuentra el BD2 otro procedimiento recibe el archivo y procesa las instrucciones del archivo de comandos.

    ---

    También existe la opción de implementar la replicación transaccional (siempre y cuando la edición SQL Server del equipo de origen no sea Express).


    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Editado José Diz lunes, 23 de septiembre de 2019 22:05
    lunes, 23 de septiembre de 2019 21:40
  • Hola Jose, 

    No estoy cuestionando tu solución entiendo lo que hiciste y porque lo hiciste sola era una duda, ultimamente estoy mas en el lado de infraestructura. Entiendo cada uno de tus puntos.


    Blog: www.sqlservertoolbox.blogspot.com.mx

    lunes, 23 de septiembre de 2019 22:14
  • ANTES de hacer uso del MERGE, puedes hacer uso de EXCEPT o INTERSECT, para disminuir el numero de registros a validar

    https://docs.microsoft.com/es-es/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql?view=sql-server-2017


    IIslas Master Consultant SQL Server

    lunes, 23 de septiembre de 2019 22:49