Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > SQL
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 27-11-2014
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Realizar un MERGE con los ADOConnection

Buenas,

Estoy intentando realizar un MERGE a una tabla en un servidor MSSQL a traves de los componentes ADO, en particular la consulta es

Código SQL [-]
merge STOCKS as target
using (values ('X3', '03', '2014-11-27', 'SA123', 3))  as source 
(EMPRESA,ALMACEN,FECHA,ARTICULO,UNIDADES)   on 
   target.empresa= source.empresa and 
   target.almacen=source.almacen and 
   target.fecha=source.fecha and 
   target.articulo=source.articulo
when matched then
    update
    set UNIDADES = source.UNIDADES
when not matched then
    insert (EMPRESA,ALMACEN,FECHA,ARTICULO,UNIDADES)
    values (
      source.EMPRESA,
      source.ALMACEN,
      source.FECHA,
      source.ARTICULO,
      source.UNIDADES,
    );

Pero siempre obtengo el error "Sintaxis incorrecta cerca de la palabra 'merge'"
He intentado ejecutarlo desde los componentes ADOCommandText, ADOQuery y directamente ejecutandolo con el ADOConnection.Execute siempre con el mismo resultado.

Dicha instrucción SQL es correcta y si la ejecuto en la aplicación Microsoft SQL Server Management Studio, se ejecuta sin problemas y obtengo los resultados esperados de inserción/actualización.

Esta consulta es en MSSQL es equivalente a hacer en MySQL un
Código SQL [-]
INSERT INTO .. ON DUPLICATE KEY UPDATE...

Comentar que estoy usando Delphi XE4, de servidor de datos MSSQL2005 y la conexión al servidor la realizo directamente a través de SQL NATIVE CLIENT.

También he intentando ejecutar dicha consulta con los componentes ZEOS, pero el resultado nuevamente ha sido el mismo.

Me da la impresión que el error al darlo en español lo este generando el SQL NATIVE CLIENT, pero ya lo actualice a la ultima versión del mismo, sin obtener ningún cambio.

Y buscando en google sobre este error tampoco he obtenido resultados.

Gracias anticipadas por su ayuda.
Responder Con Cita
  #2  
Antiguo 27-11-2014
orodriguezca orodriguezca is offline
Miembro
 
Registrado: ene 2009
Posts: 221
Poder: 16
orodriguezca Va por buen camino
En general este tipo de sentencias de actualización no puede ejecutarse con el procedimiento "open" de un dataset o estableciendo "Active" a true, por lo que casi nunca se pueden ejecutar en tiempo de diseño. Con ADO asegúrate de estar utilizando el método TADOQuery.ExecSQL en el código de la aplicación.

Por otra parte, si mal no recuerdo, la sentencia merge está disponible desde la versión SQL Server 2008. Me sorprende que funcione en SQL Server 2005.

Última edición por orodriguezca fecha: 27-11-2014 a las 15:54:02.
Responder Con Cita
  #3  
Antiguo 27-11-2014
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Hola orodriguezca, gracias por responder

En cuanto al servidor tenias razón, es la versión 2008, "Microsoft SQL Server 2008 (RTM) - 10.0.1600.22", es por eso que podía hacer el merge

En cuanto a este tipo de sentencias, es cierto que no se pueden ejecutar con un SQLQuery, pero puestos a que no he conseguido ponerlo a funcionar ya he probado con todo :-). La forma de ExecSQL es de lo poco que me quedaba, pero no ha funcionado tampoco. Originalmente se deberia de ejecutar de esta forma, muy similar al ExecSQL, pero directamente sobre el componente CONNECTION, y la ejecución siempre sera en RUNTIME, dentro de un proceso de intercambio de datos con otras tablas.

Código:
    try
      ADOConnection1.Execute(
        'merge STOCKS as target' +
        'using (values (''X3'', ''03'', ''2014-11-27'', ''SA123'', 3))  as source' +
        '(EMPRESA,ALMACEN,FECHA,ARTICULO,UNIDADES) on ' +
        '   target.empresa= source.empresa and ' +
        '   target.almacen=source.almacen and ' +
        '   target.fecha=source.fecha and ' +
        '   target.articulo=source.articulo  and ' +
        'when matched then ' +
        '    update ' +
        '    set UNIDADES = source.UNIDADES ' +
        'when not matched then ' +
        '    insert (EMPRESA,ALMACEN,FECHA,ARTICULO,UNIDADES)' +
        '    values (' +
        '      source.EMPRESA,' +
        '      source.ALMACEN,' +
        '      source.FECHA,' +
        '      source.ARTICULO,' +
        '      source.UNIDADES' +
        '    );'
      );
    except
      On E:Exception do begin
        MessageDlg(E.Message, mtError, [mbOK], 0);
      end;
    end;
Aunque tras muchas pruebas, creo que el error no esta en los componentes, si no en la pasarela de conexión que realiza un preanalisis de la sentencia bloqueandola, y no dejandola llegar al motor de B.D., pues cuando intento esto mismo con los ZEOS el error y el comportamiento es exactamente el mismo.

¿Hay alguna forma de evitar este analisis previo y que le llegue al motor de BD?? para que en caso de error sea el propio motor el que de el error
Responder Con Cita
  #4  
Antiguo 27-11-2014
orodriguezca orodriguezca is offline
Miembro
 
Registrado: ene 2009
Posts: 221
Poder: 16
orodriguezca Va por buen camino
Debería funcionar bien. Asegúrate que la aplicación se está conectando al servidor correcto. Hice una prueba con ADO y funcionó correctamente. Esto fue lo que hice:

Así establecí la cadena de conexión:

Código Delphi [-]
Provider=SQLNCLI10.1;Integrated Security=SSPI;Persist Security Info=False;User ID="";Initial Catalog=CRI_DESA;Data Source=Direccion_IP_del_Servidor;Initial File Name="";Server SPN=""

En ADOQuery1.SQL (En tiempo de diseño):
Código SQL [-]
MERGE PRUEBA1 as target
  using  PRUEBA2  AS SOURCE
  ON target.CAMPO1 = source.CAMPO1
 WHEN NOT MATCHED THEN 
   INSERT(CAMPO1) VALUES(source.CAMPO1);

Y como Acción:

Código Delphi [-]
procedure TForm14.Button1Click(Sender: TObject);
begin
  AdoQuery1.ExecSQL;
  ShowMessage('Prueba terminada');
end;
Responder Con Cita
  #5  
Antiguo 27-11-2014
orodriguezca orodriguezca is offline
Miembro
 
Registrado: ene 2009
Posts: 221
Poder: 16
orodriguezca Va por buen camino
Revisando un poco más en detalle tu código creo que el problema puede estar en la concatenacion:

Código Delphi [-]
 ADOConnection1.Execute(
        'merge STOCKS as target' +
        'using (values (''X3'', ''03'', ''2014-11-27'', ''SA123'', 3))  as source' +
        '(EMPRESA,ALMACEN,FECHA,ARTICULO,UNIDADES) on ' +

Al concatenar la cadena quedaría como
Código Delphi [-]
 ADOConnection1.Execute('merge STOCKS as targetmerge STOCKS as targeusing (values (''X3'', ''03'', ''2014-11-27'', ....

Coloca al menos un espació al final de cada literal de cadena:
Código Delphi [-]
ADOConnection1.Execute(
        'merge STOCKS as target ' +
        'using (values (''X3'', ''03'', ''2014-11-27'', ''SA123'', 3))  as source ' +
        '(EMPRESA,ALMACEN,FECHA,ARTICULO,UNIDADES) on ' +
        '   target.empresa= source.empresa and ' +
        '   target.almacen=source.almacen and ' +
Responder Con Cita
  #6  
Antiguo 27-11-2014
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Gracias orodriguezca por tus respuestas.

Finalmente ya conseguí que funcionara, parece ser que se trataba de un problema de versiones del SQLNCLI, pues tenia instalada la versión 9 (necesaria para un programa de terceros) y la versión 10. He desinstalado ambas versiones y las he vuelto a instalar. Y ya si he conseguido que funcione.

Es cierto que el tema de los espacios en el corte de la sentencia era un error, pues no había espacio entre el final de linea y el siguiente, pero es que anteriormente no llegaba a marcar ni siquiera ese error a nivel sintáctico.

Después de algún tiempo haciendo intentos y de buscar información al respecto estaba ya por buscar soluciones alternativas a este problema, pensando que pudiera tratarse de un BUG del proveedor de datos.

Gracias de nuevo por tu ayuda y tu tiempo.
Responder Con Cita
  #7  
Antiguo 27-11-2014
orodriguezca orodriguezca is offline
Miembro
 
Registrado: ene 2009
Posts: 221
Poder: 16
orodriguezca Va por buen camino
bucanero, Me alegra que se haya solucionado el problema.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Merge Module Firebird mjjj Firebird e Interbase 5 29-01-2008 15:15:27
InstallShield y BDE Merge Module manitoba Varios 0 14-03-2007 20:02:50
Mail Merge con Word JavierSotillos Varios 0 20-10-2006 13:19:43
merge mail PiPerraK Varios 4 30-08-2005 17:53:11
Merge Modules son necesarios? m@r Varios 2 14-01-2005 17:08:20


La franja horaria es GMT +2. Ahora son las 01:31:17.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi