Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » SQL Server »

[SOLUCIONADO] Openquery y merge

Estas en el tema de Openquery y merge en el foro de SQL Server en Foros del Web. Buenos días a todos! En un servidor de SQL Server2012 tengo vinculado/linkado uno de MySql. Intento actualizar datos desde SQLServer hacia Mysql con merge, de ...
  #1 (permalink)  
Antiguo 20/06/2016, 06:23
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Pregunta Openquery y merge

Buenos días a todos!

En un servidor de SQL Server2012 tengo vinculado/linkado uno de MySql. Intento actualizar datos desde SQLServer hacia Mysql con merge, de la siguiente forma:

Código SQL:
Ver original
  1. MERGE INTO OPENQUERY(SERVIDOR_MYSQL, 'SELECT campo1, campo2, campo3, campo4 FROM [SRV_VINCULADO].[bd].[tabla1]') AS DESTINO
  2. USING [BD_ORIGEN].[dbo].[tabla1] AS ORIGEN
  3.     ON (ORIGEN.campo1 = DESTINO.campo1 AND ORIGEN.campo2 = DESTINO.campo2)
  4. WHEN MATCHED THEN UPDATE
  5.     SET DESTINO.campo3 = ORIGEN.campo3,
  6.         DESTINO.campo4 = ORIGEN.campo4
  7. WHEN NOT MATCHED THEN INSERT
  8.     VALUES(ORIGEN.campo1,
  9.            ORIGEN.campo2,
  10.            ORIGEN.campo3,
  11.            ORIGEN.campo4)
  12. WHEN NOT MATCHED BY SOURCE THEN DELETE;

El problema está en el alias 'DESTINO', pues no me lo reconoce y no puedo hacer el update.

He probado varias opciones para intentar solucionarlo como ésto
Código SQL:
Ver original
  1. MERGE INTO OPENQUERY(SERVIDOR_MYSQL, 'SELECT campo1, campo2, campo3, campo4 FROM tabla1') AS DESTINO
  2. MERGE INTO OPENQUERY(SERVIDOR_MYSQL, 'SELECT campo1, campo2, campo3, campo4 FROM [SRV_VINCULADO].[tabla1]') AS DESTINO

pero nada , por favor alguien me podría ayudar?

Saludos y gracias

Última edición por Azor; 20/06/2016 a las 07:54
  #2 (permalink)  
Antiguo 22/06/2016, 04:21
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Respuesta: Openquery y merge

Bueno, por suerte una alma caritativa (a la que le agradezco mucho la ayuda), me echó una mano indicándome que utilizara una CTE para mi sql, quedando algo parecido a ésto:
Código SQL:
Ver original
  1. WITH DESTINO AS (
  2.    SELECT empresa, campo1, campo2, campo3, campo4
  3.    FROM OPENQUERY(SERVIDOR_MYSQL, 'campo1, campo2, campo3, campo4 FROM SRV_VINCULADO.bd.tabla1')
  4. )
  5. MERGE INTO DESTINO
  6. USING ([BD_ORIGEN].[dbo].[tabla1]) AS ORIGEN
  7.    ON (ORIGEN.campo1 = DESTINO.campo1 AND ORIGEN.campo2 = DESTINO.campo2)
  8.  WHEN MATCHED THEN UPDATE
  9.       SET DESTINO.campo3 = ORIGEN.campo3,
  10.           DESTINO.campo4 = ORIGEN.campo4
  11. WHEN NOT MATCHED THEN INSERT
  12.       VALUES(ORIGEN.campo1,
  13.              ORIGEN.campo2,
  14.              ORIGEN.campo3,
  15.              ORIGEN.campo4)
  16. WHEN NOT MATCHED BY SOURCE THEN DELETE;

Con lo cual, el alias ya no es un problema, pero la selec ahora me devuelve el siguiente error:
"El destino de una instrucción MERGE no puede ser una tabla remota, una vista remota o una vista sobre tablas remotas"
Merge me facilita mucho el trabajo a la hora de estar actualizando/insertando registros en mysql, pero parece que tiene la "limitación" que describe el error anterior.

El servidor de SQLSERVER lo tengo en local, pero el de MYSQL está alojado fuera.

El sentido de la inserción siempre sería de SQLSERVER > MYSQL, nunca a la inversa.

Alguien se ha encontrado con algo parecido?


Muchas gracias!
  #3 (permalink)  
Antiguo 22/06/2016, 06:26
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Respuesta: Openquery y merge

Hola de nuevo!

Igual estoy intentando solucionar el problema de forma equivocada, por lo que les planteo el objetivo de nuevo a ver si alguien me puede orientar de alguna forma.

Objetivo general:
Necesito poder leer registros de tablas de una bd sqlserver que está en local y grabarlos o actualizarlos en una bd mysql remota.

Para conseguir el objetivo pensé en linkar los dos servidores de SQLServer.
Utilizar la sentencia Merge me parecía la opción ideal para sincronizar la información entre los dos servidores, pero parece "merge" no puede grabar datos en una tabla de un servidor remoto, ¿qué otro planteamiento podrían ofrecerme para conseguir mi objetivo?

¿Alguna idea?

Saludos.
  #4 (permalink)  
Antiguo 22/06/2016, 07:53
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 17 años, 8 meses
Puntos: 774
Respuesta: Openquery y merge

El clasico insert donde no esta update donde si usando left joins :)

Código SQL:
Ver original
  1. INSERT INTO tabla_destino
  2. SELECT * FROM tabla_origen AS t1
  3. LEFT JOIN tabla_destino AS t2 ON (t1.id=t2.id)
  4. WHERE t2.id IS NULL
  5.  
  6. UPDATE tabla_destino
  7. SET valor=completa.valor
  8. FROM
  9. (
  10. SELECT * FROM tabla_origen AS t1
  11. LEFT JOIN tabla destino AS t2 ON (t1.id=t2.id)
  12. WHERE t2.id IS NOT NULL
  13. ) AS completa WHERE completa.id=tabla_destino.id

Que eso es lo miso que hace un merge......
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #5 (permalink)  
Antiguo 22/06/2016, 08:16
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Respuesta: Openquery y merge

Hola Libras!

Muchas gracias por la ayuda , voy a probar lo que me comentas.

Disculpa mi ignorancia, entiendo que lo ideal para automatizar la tarea, sería crear un primer job en la bd para hacer el insert y cuando éste acabe lanzar un segundo para el update, no?

Gracias de nuevo.
  #6 (permalink)  
Antiguo 22/06/2016, 09:31
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 17 años, 8 meses
Puntos: 774
Respuesta: Openquery y merge

No, no ocupas 2 jobs con uno solo puedes hacer las 2 operaciones, cual seria el objetivo de los 2 jobs???

Ahora si estas haciendo esto para tener replicados tus datos en ambos servidores, porque no investigas acerca de las tecnologias de alta disponibilidad de sql server
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #7 (permalink)  
Antiguo 22/06/2016, 16:12
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Respuesta: Openquery y merge

Lo de los dos Jobs seria para asegurarme que no se ejecuta el update sin haber acabado el insert primero, sobretodo cuan son muchos los registros a tratar

No trato de replicar toda la información de la bd de sql server, más bien quiero tener información actualizada con registros de ciertos campos y tablas en un base de datos a parte, para poder atacarla desde una aplicación.

De todas formas me viene que ni pintando lo que me comentas de las tecnologías de alta capacidad de sql server, pues tengo pendiente el tema de replicación la bd en otro servidor por si cae el principal. Todo llegará
  #8 (permalink)  
Antiguo 22/06/2016, 16:38
Avatar de iislas
Colaborador
 
Fecha de Ingreso: julio-2007
Ubicación: Mexico, D.F.
Mensajes: 6.482
Antigüedad: 16 años, 9 meses
Puntos: 180
Respuesta: Openquery y merge

Si no va a MODIFICAR los datos que estaran en la base "replicada", puede implementar la creacion de una base de tipo INSTANTANEA (Snapshot), solo como observacion, debe tener la edicion ENTERPRISE
__________________
MCTS Isaias Islas
  #9 (permalink)  
Antiguo 22/06/2016, 18:08
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 17 años, 8 meses
Puntos: 774
Respuesta: Openquery y merge

Cita:
Iniciado por Azor Ver Mensaje
Lo de los dos Jobs seria para asegurarme que no se ejecuta el update sin haber acabado el insert primero, sobretodo cuan son muchos los registros a tratar
Los queries en sql se ejecutan de manera secuencial, hasta que termina el primero sigue con el segundo por lo que un

insert......

update....

primero insertara los registros y cuando termine de insertar continuara con la parte del update
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #10 (permalink)  
Antiguo 23/06/2016, 01:04
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Respuesta: Openquery y merge

Cita:
Iniciado por iislas Ver Mensaje
Si no va a MODIFICAR los datos que estaran en la base "replicada", puede implementar la creacion de una base de tipo INSTANTANEA (Snapshot), solo como observacion, debe tener la edicion ENTERPRISE
Hola iislas!
No en principio no se van a modificar los datos del servidor replicado, solo se modificarían o utilizarían en el caso de que el servidor principal fallara.
Muchas gracias por el apunte.

Cita:
Iniciado por Libras Ver Mensaje
Los queries en sql se ejecutan de manera secuencial, hasta que termina el primero sigue con el segundo por lo que un
insert......
update....
primero insertara los registros y cuando termine de insertar continuara con la parte del update
Hola Libras!
Entendido y muchísimas gracias por la ayuda y la paciencia.
Sólo un apunte más, creo que en ocasiones no se valora lo suficiente lo que supone encontrar respuestas cuando uno necesita soluciones y acude a foros como éste.
Es de admirar lo que haces tú y el resto de usuarios aportando de forma altruista su tiempo, conocimientos y experiencia para AYUDAR a los demás.
GRACIAS
  #11 (permalink)  
Antiguo 23/06/2016, 06:32
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Respuesta: Openquery y merge

Hola de nuevo Libras!

He estado probando y con el insert no tengo problemas, quedaría el sql así:

Código SQL:
Ver original
  1. INSERT INTO OPENQUERY(SERVIDOR_MYSQL,'SELECT campo1, campo2, campo3, campo4 FROM BD.tabla1')
  2.    SELECT ORIGEN.campo1, ORIGEN.campo2, ORIGEN.campo3, ORIGEN.campo4
  3.      FROM [BD_ORIGEN].[dbo].[tabla1] AS ORIGEN
  4. LEFT JOIN OPENQUERY(SERVIDOR_MYSQL,'SELECT campo1, campo2, campo3, campo4 FROM BD.tabla1') AS DESTINO
  5.        ON (ORIGEN.campo1 = DESTINO.campo1 AND ORIGEN.campo2 = DESTINO.campo2)
  6.     WHERE (DESTINO.campo1 IS NULL AND DESTINO.campo2 IS NULL)

pero con el update me da el siguiente error, aunque acaba haciendo los cambios:
"El proveedor OLE DB "MSDASQL" del servidor vinculado "XXXXXXXX" devolvió el mensaje "No se puede encontrar la fila para su actualización: algunos valores han cambiado desde la última vez que se leyó.".
Mens. 7343, Nivel 16, Estado 4, Línea 1
El proveedor OLE DB "MSDASQL" del servidor vinculado "XXXXXXXXI" no pudo UPDATE la tabla "[MSDASQL]". El conjunto de filas utiliza simultaneidad optimista y el valor de una columna ha cambiado desde que se capturó o"
La sql sería ésta:
Código SQL:
Ver original
  1. WITH DESTINO AS (
  2.    SELECT campo1, campo2, campo3, campo4
  3.    FROM OPENQUERY(SERVIDOR_MYSQL, 'SELECT campo1, campo2, campo3, campo4 FROM BD.tabla1')
  4. )
  5. UPDATE DESTINO
  6.   SET DESTINO.campo1 = COMPLETA.campo1,
  7.       DESTINO.campo2 = COMPLETA.campo2,
  8.       DESTINO.campo3 = COMPLETA.campo3,
  9.       DESTINO.campo4 = COMPLETA.campo4
  10. FROM
  11. (
  12. SELECT ORIGEN.campo1, ORIGEN.campo2, ORIGEN.campo3, ORIGEN.campo4
  13.      FROM [BD_ORIGEN].[dbo].[tabla1] AS ORIGEN
  14. LEFT JOIN OPENQUERY(SERVIDOR_MYSQL,'SELECT campo1, campo2, campo3, campo4 FROM BD.tabla1') AS DESTINO
  15.        ON (ORIGEN.campo1 = DESTINO.campo1 AND ORIGEN.campo2 = DESTINO.campo2)
  16.     WHERE (DESTINO.campo1 IS NOT NULL AND DESTINO.campo2 IS NOT NULL)
  17. ) AS COMPLETA
  18. WHERE (COMPLETA.campo1 = DESTINO.campo1 AND COMPLETA.campo2 = DESTINO.campo2)

Ves alguna o varias cosas mal en la sql del update?
  #12 (permalink)  
Antiguo 24/06/2016, 05:48
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Respuesta: Openquery y merge

Me da la impresión que el error se produce por la select del with y la del left join, pero no sé cómo darle otro enfoque a pesar de haber deshecho y rehecho la select varias veces..
alguna idea?

Última edición por Azor; 24/06/2016 a las 15:13
  #13 (permalink)  
Antiguo 27/06/2016, 07:05
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Respuesta: Openquery y merge

Por lo que he estado viendo el servidor de sql server se puede configurar de maneras distintas:
En modo "simultaneidad optimista" o "simultaneidad pesimista".
Mi servidor lo tengo configurado con la primera opción y de ahí el mensaje que me aparece cuando intento el update, por culpa de las dos selects con openquerrry que hago (o eso entiendo yo). Una sobre la parte del with y la otra sobre la línea de left join. No voy a cambiar la configuración del servidor dado que tengo otras bds.

Por lo que creo que debería intentar cambiar mi sql. He estado mirando otro caso similar al mío en el foro que no había visto antes, (lo siento), es éste:
http://www.forosdelweb.com/f87/delet...culado-819142/

En el que se cambia la select que se hace y consigue evitar el error. Si inteno readaptar mi sentencia de update me encuentro que donde se cambia el join por el exist se hace sobre dos tablas de la misma bd, en cambio yo tengo una tabla en el servidor de remoto o linkado de MySql y la otra sobre el servidor local Sql Server y no se como retocar la sql para que funcione.

Por favor ¿alguna ayuda u orientación?

Gracias.
  #14 (permalink)  
Antiguo 28/06/2016, 16:20
 
Fecha de Ingreso: febrero-2014
Ubicación: España
Mensajes: 60
Antigüedad: 10 años, 1 mes
Puntos: 1
Respuesta: Openquery y merge

No sé si es la solución o sólo una chapuzilla pero dejando la sql de la siguiente forma funciona:

Código SQL:
Ver original
  1. WITH DESTINO AS (
  2.    SELECT empresa, alm, txt, orden, admitepedidos, email
  3.    FROM OPENQUERY(SERVIDOR_MYSQL, 'SELECT empresa, alm, txt, orden, admitepedidos, email FROM SERVIDOR_MYSQL.almacen')
  4. )
  5. UPDATE DESTINO
  6.   SET DESTINO.txt = COMPLETA.txt,
  7.       DESTINO.orden = COMPLETA.orden,
  8.       DESTINO.admitepedidos = COMPLETA.admitepedidos,
  9.       DESTINO.email = COMPLETA.email
  10. FROM (SELECT ORIGEN.empresa, ORIGEN.alm, ORIGEN.txt, ORIGEN.orden, ORIGEN.admitepedidos, ORIGEN.email
  11.         FROM [SERVIDOR_SQL_SERVER].[dbo].[almacen] ORIGEN
  12.    LEFT JOIN OPENQUERY(SERVIDOR_MYSQL,'SELECT empresa, alm, txt, orden, admitepedidos, email FROM SERVIDOR_MYSQL.almacen') AS DESTINO
  13.           ON (ORIGEN.empresa = DESTINO.empresa AND ORIGEN.alm COLLATE Modern_Spanish_100_CI_AS = DESTINO.alm COLLATE Modern_Spanish_100_CI_AS)
  14.        WHERE (DESTINO.empresa IS NOT NULL AND DESTINO.alm IS NOT NULL)
  15.          AND ((DESTINO.txt COLLATE Modern_Spanish_100_CI_AS <> ORIGEN.txt COLLATE Modern_Spanish_100_CI_AS)
  16.           OR (DESTINO.orden <> ORIGEN.orden)
  17.           OR (DESTINO.admitepedidos <> ORIGEN.admitepedidos)
  18.           OR (DESTINO.email COLLATE Modern_Spanish_100_CI_AS  <> ORIGEN.email COLLATE Modern_Spanish_100_CI_AS))) AS COMPLETA
  19. WHERE (COMPLETA.empresa = DESTINO.empresa AND COMPLETA.alm COLLATE Modern_Spanish_100_CI_AS = DESTINO.alm COLLATE Modern_Spanish_100_CI_AS);

Cuando hacía el update sobre registros en los que no se cambiaba nada, es decir que los campos de la tabla origen tenía los mismos valores que los de la tabla destino, se producía el archiconocido error, pero al añadir las líneas:

Código SQL:
Ver original
  1. ...
  2.           OR (DESTINO.orden <> ORIGEN.orden)
  3.           OR (DESTINO.admitepedidos <> ORIGEN.admitepedidos)
  4.           OR (DESTINO.email COLLATE Modern_Spanish_100_CI_AS  <> ORIGEN.email COLLATE Modern_Spanish_100_CI_AS)))

funciona todo correcto. Si existían registros en los que si se hacía el update de los datos, no me daba error alguno.

También resulta curioso que cuando hago un update directamente sobre la tabla almacen de la base de datos de mysql desde el workbenchy y los campos a actualizar tienen el mismo valor que los campos destino, secillamente dice: 0 rows afected, pero no da ningún error.

En fin, seguro que existen soluciones mejores, pero es lo único que he podido hacer.

Etiquetas: insert, select, server
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 04:06.