Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Problema Firedac Sql Advantagedatabase 12 Multiple Row Insert (https://www.clubdelphi.com/foros/showthread.php?t=92313)

amadis 26-09-2017 02:26:42

Problema Firedac Sql Advantagedatabase 12 Multiple Row Insert
 
Que tal colegas.

Estoy intentando optimizar una rutina que guarda detalles del contenido de una compra.

La idea era hacerlo mediante un insert de multiple row.

En otras oportunidades he hecho algo similar pero insertando de una valores prefijados con anterioridad.

Pero en este caso lo que quiero es que mediante la ejecucion de un solo FDSqlQuery pueda agregar varios registros con el detalle de una compra. Y me está dando un error luego de la linea 4.

Código Delphi [-]
        QryGuardaDet.SQL.Clear;
        QryGuardaDet.SQL.Append('insert into detalle');
        QryGuardaDet.SQL.Append('(articulo,cantidad,comprobante)');
        QryGuardaDet.SQL.Append('values');

        datos.CDSDetalle.DisableControls;
        if datos.CDSDetalle.State = dsinsert  then datos.CDSDetalle.cancel;
        datos.CDSDetalle.First;


     for i := 1 to datos.CDSDetalle.RecordCount-1
         do
          begin
              QryGuardaDet.SQL.Append('(:art, :cant, :com),');
              QryGuardaDet.ParamByName('art').AsString := datos.CDSDetalleFarticulos.Value;
              QryGuardaDet.ParamByName('cant').Value := datos.CDSDetalleFcant.AsFloat;
              QryGuardaDet.ParamByName('com').AsInteger := codfact;
              
              datos.CDSDetalle.Next;
          end;
             QryGuardaDet.SQL.Append('(:art, :cant, :com);');//linea final con puntoycoma
              QryGuardaDet.ParamByName('art').AsString := datos.CDSDetalleFarticulos.Value;
              QryGuardaDet.ParamByName('cant').Value := datos.CDSDetalleFcant.AsFloat;
              QryGuardaDet.ParamByName('com').AsInteger := codfact;

Los datos que cargo en los parametros que pretendo reusar una y otra vez estan en un clientdataset, dentro de un datamodule.

Me da error en la linea 4, se esperaba PUNTOYCOMA, cuando deberia aceptarme la COMA ya que luego del bucle le agrego el puntoycoma.

Quizá pueda ser algun error con las comillas o algo similar.

O no se si se pueden usar los mismos parametros.

Toda luz será bienvenida.

Casimiro Notevi 26-09-2017 09:33:01

No entiendo la lógica de lo que estás haciendo, aunque de todas formas, a simple vista diría que lo que está mal es esa coma del final.
Código Delphi [-]
QryGuardaDet.SQL.Append('(:art, :cant, :com),');

amadis 26-09-2017 10:17:00

La lógica de la sintaxis que estoy usando es la siguiente

Código SQL [-]
INSERT INTO table1 (First, Last)
VALUES
    ('Fred', 'Smith'),
    ('John', 'Smith'),
    ('Michael', 'Smith'),
    ('Robert', 'Smith');

Los valores los tendo en un clientdataset creado en memoria.

Si asigno los valores prefijados como en este ejemplo de recién funciona.

Pero al poner en juego los parámetros, al final de la linea 4, me dice que NO ESPERA LA COMA, que espera PUNTOYCOMA.
Le pongo punto y coma que no corresponde y ejecuta la linea 4 y en la 5, se para diciendo que debo iniciar con INSERT. ETC ETC.

Yo estaba usando ese query una y otra vez hasta que termine el clientdataset, pero se me ocurrió que podría optimizarse de esa forma.

amadis 26-09-2017 10:41:54

Recién al ver el ejemplo que puse de sintaxis, se me ocurrió ponerle QUOTEDSTR, al valor del primer parámetro.

Y funcionó, se ejecutó el query, pero no resultó como quería, aunque lo sospechaba.

me insertó tantos registros como había en el clientdataset, pero todos con el último valor, lógico, porque los parametros que usé son los mismos. Por un momento pensé que podía funcionar.

ecfisa 26-09-2017 12:53:16

Hola.

Al parecer te falta la condición, vg.:
Código Delphi [-]
    QryGuardaDet.SQL.Clear;
    QryGuardaDet.SQL.Append('insert into detalle');
    QryGuardaDet.SQL.Append('(articulo,cantidad,comprobante)');
    QryGuardaDet.SQL.Append('values');
    QryGuardaDet.SQL.Append('(:art, :cant, :com),');
    QryGuardaDet.SQL.Append('WHERE CAMPO_CLAVE = :PARAM');
    
    for ....
    begin
      QryGuardaDet.ParamByName('art').AsString := datos.CDSDetalleFarticulos.Value;
      QryGuardaDet.ParamByName('cant').Value := datos.CDSDetalleFcant.AsFloat;
      QryGuardaDet.ParamByName('com').AsInteger := codfact
      QryGuardaDet.ParamByName('PARAM').Value := (lo que corresponda)
    ...

Saludos :)

amadis 26-09-2017 13:27:41

No tengo condición.

Inserto en la tabla todos los registros que hay en el Clientdataset. que tienen el dato del articulo facturado, la cantidad y el numero de comprobante.

AgustinOrtu 26-09-2017 18:24:49

Es lo que dice casimiro, la coma luego de la lista de parametros no va

bitbow 26-09-2017 18:32:08

Extrae tu sql resultante (SQL.Text) y valida la sintaxis (reemplaza los params por valores) y ejecutalo en un cliente independiente.

Saludos.

amadis 26-09-2017 18:44:19

La sintaxis está correcta, luego de ponerle el QuotedStr que comenté al parametro String, funcionó.
Solamente que el problema lógico ahora es que reutilizo los mismos parametros, y al recorrer el ClientDatasat, si este tiene 5 registros, e nel query se agregan las cinco lineas de parámetros y asigna el valor y una a una, pero como el nombre de los parametros es la mismo, en definitiva me guardó 5 veces el registro último.

La COMA del final ES CORRECTA, ya que delimita el grupo de valores, y recorro el ClientDataset hasta -1 para luego en el proximo sqlstring reemplazar la COMA por PUNTOyCOMA, indicando fin de valores.


Lo que tendria que hacer es crear parametros multiplicados por los N registros tenga en el clientdataset.
Nombaralos igual agregando el numero del registro

de esa forma los primeros parametros serían (:art1, :cant1, :com1), luego (:art2, :cant2, :com2) y sucesivamente.

ecfisa 26-09-2017 23:03:49

Hola.
Cita:

Empezado por amadis (Mensaje 521329)
No tengo condición.

Inserto en la tabla todos los registros que hay en el Clientdataset. que tienen el dato del articulo facturado, la cantidad y el numero de comprobante.

Entonces te interpreté mal. Aunque hay algunos puntos que desconozco, creo que lo que buscas sería mas o menos así:
Código Delphi [-]
...
begin
  QryGuardaDet.Close;
  QryGuardaDet.SQL.Clear;
  QryGuardaDet.SQL.Add('INSERT INTO DETALLE(ARTICULO, CANTIDAD, COMPROBANTE)');
  QryGuardaDet.SQL.Add('VALUES(:ART, :CAN, :COM)');
  QryGuardaDet.Prepare;

  while not datos.CDSDetalleFcant.Eof do
  begin
    QryGuardaDet.ParamByName('ART').Value := datos.CDSDetalleFarticulos.Value;
    QryGuardaDet.ParamByName('CAN').Value := datos.CDSDetalleFcant.Value;
    QryGuardaDet.ParamByName('CON').Value := xxx {valor de comprobante que corresponda};
    QryGuardaDet.ExecSQL;  // ejecutar la consulta de actualización
    datos.CDSDetalleFcant.Next;
  end;
  ...
end;

Saludos :)

amadis 27-09-2017 00:32:32

Si seria eso, suena a que va a funcionar, ya que ejecuta el query en cada registro. y asigna los valores a los parametos.

Yo desconocia la funcion del PREPARE, y en cada registro repetía todos los pasos anteriores.


La franja horaria es GMT +2. Ahora son las 08:34:46.

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