Problema con cláusula RETURNING en Firebird

158 views
Skip to first unread message

Ultraton500

unread,
Feb 7, 2015, 5:06:07 PM2/7/15
to publice...@googlegroups.com
Buenas tardes a todos, estoy intentando obtener el nro. de id del registro que inserto usando la cláusula RETURNING pero obtengo un error que me indica que el problema está en donde empieza la variable.
Estoy utilizando la librería FoxyDB y lo hago de esta manera:

FoxyDb.SQL("INSERT INTO tabla (campo1,...) VALUES (" + variable1,... + ") RETURNING id_tabla INTO V1")

Probe también con ":V1" pero nada cambia.

La sentencia sin el RETURNING funciona bien.
Alguien podría indicarme la manera correcta de hacerlo y si me voy a poder referir luego a la variable "V1" como a cualquier otra dentro de vfp?.

Desde ya muchas gracias.
Saludos,
Javier.

mapner

unread,
Feb 7, 2015, 5:11:39 PM2/7/15
to publice...@googlegroups.com
La cláusula INTO solo es brindada en PSQL o sea, en Store Procedures o Triggers, probá la misma sentencia sin INTO.

Saludos

Ultraton500

unread,
Feb 7, 2015, 5:53:28 PM2/7/15
to publice...@googlegroups.com
Gracias mapner por la ayuda.
Probé sin INTO y la sentencia SQL funciona bien, ahora lo que me falta saber es cómo obtengo el valor devuelto con RETURNING.

Saludos cordiales,
Javier.

Antonio Meza

unread,
Feb 7, 2015, 11:34:00 PM2/7/15
to publice...@googlegroups.com
Hola Javier!!

Hay 2 formas de hacerlo con FoxyDb,

* Automática, no tienes que generar ningún comando SQL y obtienes el ultimo ID sin problemas, pasos:
1 Abrir la tabla del servidor firebird
foxydb.Use("tabla")
2 Preparar el cursor devuelto para edición.
foxydb.CursorEdit("tabla")
3 Insertar un registro nuevo ya usando comandos de VFP
Append Blank o puedes usar insert into 
4 Enviar a actualizar los datos al servidor con el parámetro .T. para que devuelva el ultimo Id insertado
foxydb.Update("tabla",.t.)
5 Mostrar el ultimo id insertado
wait windows foxydb.id_last
6 Guardar los cambios en el servidor
foxydb.Save

Si vas a usar la forma Manual, entonces primero tienes que iniciar una transacción, ya que el comando foxydb.SQL() activa una transacción de solo lectura para mejorar el rendimiento, realiza la consulta y la termina, por lo tanto tienes que iniciar una transacción de forma manual para que ya puedas enviar el comando SQL sin problemas, y luego solo guardar los cambios. seria algo así

Si usas la versión 1.11 seria así
foxydb.begin
* Aquí tienes que generar el SQL para insertar y devolver el ultimo id
foxydb.Sql("insert into ........") RETURNING ...
* Aquí mostrar el ultimo ID insertado
foxydb.save

Si usas 1.10
foxydb.Transaction(2)
* Aquí tienes que generar el SQL para insertar y devolver el ultimo id
foxydb.Sql("insert into ........") RETURNING ...
* Aquí mostrar el ultimo ID insertado
foxydb.save

NOTA: En teoría parece ser mas fácil de la forma manual, sin embargo tienes que investigar sobre como obtener el ultimo ID, generar el SQL Insert Into, y luego si ese valor se lo vas a guardar en otra tabla pues tienes que preparar el SQL Update, y todo eso de la forma automática lo haces usando comandos nativos de VFP, como seria un Replace para remplazar el valor de un campo en una tabla.

saludos
Antonio Meza

mpulla

unread,
Feb 8, 2015, 9:06:21 AM2/8/15
to publice...@googlegroups.com
Hola Javier.

No conosco FoxyDB y Firebird, pero por lo que acabo de leer que FoxyDB soporta CTE,

Manda esta cadena a FoxyDB, pienso debe fucnionar.

With t
As
(
Insert Into table (c1, c2...) Values (" + variabla1, ...+ ") returning id_tabla"
)
Select *
 From t

Saludos.
Mauricio

Ultraton500

unread,
Feb 8, 2015, 3:43:12 PM2/8/15
to publice...@googlegroups.com
Hola Antonio, gracias por la respuesta, se entendió muy bien.
Estoy usando la forma manual con la versión 1.11 y lo que no encuentro es la manera de saber cómo obtener el ID insertado por el INSERT que se acaba de ejecutar (el que me devuelve RETURNING), que no siempre va a ser el último id insertado. Resolviendo esto resuelvo mi problema.

Por las dudas describo a continuación mi escenario.
Importo a mi sistema 2 tablas libres provenientes de uno de los vendedores:

- cotizaciones_importadas.dbf:   contiene registros de los datos de cada cotización. Cada cotización tiene un id.
- items_importados.dbf:   contiene registros de los ítems de esas cotizaciones. Cada ítem tiene un campo con el id de la cotización a la que pertenece.

Lo que debo hacer es pasar las cotizaciones de cotizaciones_importadas.dbf a la tabla correspondiente en la db y lo mismo debo hacer con los ítems.
El inconveniente aquí es que el id de cada cotización insertada en la db va a ser diferente al de cotizaciones_importadas.dbf y entonces se pierde la correspondencia con los ítems. Para evitarlo debo, por cada cotización insertada en la db, obtener el nuevo id y reemplazarlo por el original en items_importados.dbf (en el campo que hace referencia a la cotización), luego, una vez insertadas todas las cotizaciones guardo directamente los ítems manteniendo así la correspondencia.

Otra forma sería guardar primero los ítems y luego por cada cotización insertada ejecutar un trigger que reemplace, en los ítems, el viejo id por el nuevo pero como tengo todo ya terminado quisiera ver si es posible obtener el nuevo id en cada INSERT.

Gracias nuevamente.
Saludos cordiales,
Javier.

Ultraton500

unread,
Feb 8, 2015, 3:59:46 PM2/8/15
to publice...@googlegroups.com
Hola Mauricio, gracias por la ayuda.
Probé lo sugerido pero me da error indicando el comienzo de la palabra INSERT. Pareciera no poder interpretar la sentencia con el "WITH t AS ("
Te pregunto.. lo que obtendría con Select * From t es lo devuelto por RETURNIG?

Saludos cordiales,
Javier.

Ultraton500

unread,
Feb 8, 2015, 4:41:47 PM2/8/15
to publice...@googlegroups.com
Bueno, problema resuelto!!!
Se me ocurrió probar lo menos pensado... que el valor devuelto se guarda en una variable con el mismo nombre y tipo de campo... y así es.

FoxyDB.SQL("INSERT INTO tabla (titulo) VALUES ('titulo 1') RETURNING id_tabla,titulo")

MESSAGEBOX(STR(id_tabla))        <--- muestra el nuevo id
MESSAGEBOX(titulo)                        <--- muestra "titulo 1"

Muchas gracias mapner, Antonio y Mauricio por ayudarme.
Saludos cordiales,
Javier.

Mauricio Pulla

unread,
Feb 8, 2015, 7:40:16 PM2/8/15
to publice...@googlegroups.com

Hola Javier

El error puede ser por la sintaxis y te va a devolver los valores del returning

Saludos
Mauricio

Ultraton500

unread,
Feb 8, 2015, 9:26:41 PM2/8/15
to publice...@googlegroups.com
Gracias Mauricio, voy a revisar la sintaxis.

Saludos cordiales,
Javier.

Antonio Meza

unread,
Feb 9, 2015, 11:17:26 AM2/9/15
to publice...@googlegroups.com
Hola, veo que ya lo resolviste!!

La forma en que lo haría seria automática, no conozco los nombres de tus campos pero espero y lo entiendas, si observas no tuve que enviar ningún comando SQL a FireBird, y todo con código VFP, claro usando Foxydb jejej

1 Abrir las tablas del servidor firebird
     foxydb.Use("fb_cotizaciones")
     foxydb.Use("fb_cotizaciones_items")
2 Preparar para edición.
     foxydb.CursorEdit("fb_cotizaciones")
     foxydb.CursorEdit("fb_cotizaciones_items")
3 Abrir tablas libres
     Use cotizaciones_importadas.dbf  in 0
     Use items_importados.dbf in 0
4 Recorrer la tabla libre 
     Select cotizaciones_importadas
     SCAN
          insert into fb_cotizaciones (...) values (...)
          * obtener el Ultimo Id
          foxydb.Update("fb_cotizaciones",.t.)
          * Agregar detalle y asignar ID
          Select items_importados
          scan where idCotiza = cotizaciones_importadas.idCotiza
               insert into fb_cotizaciones_items (idCotiza,....) values (foxydb.id_last, .....)
          endscan

          Select cotizaciones_importadas
     ENDSCAN

     * Actualizar la tabla detalles
     foxydb.Update("fb_cotizaciones_items")
     * Guardar todo, es decir aplicar Commit
     foxydb.Save()

saludos
Antonio Meza

Ultraton500

unread,
Feb 9, 2015, 12:05:45 PM2/9/15
to publice...@googlegroups.com
Así es Antonio, ya lo resolví pero igualmente el código que escribiste me es interesante. Todavía no he usado cursores editables con FoxyDB pero tarde o temprano voy a necesitar implementarlo y por lo tanto este ejemplo me viene muy bien.
Muchas gracias.

Saludos cordiales,
Javier.
Reply all
Reply to author
Forward
0 new messages