FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
|||
|
|||
¿Firebird Ibexpress y maestro detalle capturar id de registro recien ingresado?
Hola..
estoy haciendo una aplicacion que maneje facturas y sus items con Firebird Ibexpress y maestro detalle ¿ se puede capturar id de un registro recien ingresado? ejemplo factura serie ventassucursal1 folio 00001 cantidad descripcion precio total 2 cajas 10 20 2 sillones 100 20 2 tv LCD 10 000 20 000 yo lo que siempre he hecho es una tabla factura y otra tabla detalle relacionadas. en una relacion maestro detalle basandome en el ID de la factura y en la tala detalle ese ID de la factura es el que uso para la Foreing Key. hago un insert into facturas del encabezado serie, folio, clienterfc, emisorrfc como la tabla es autonumerica se genera el ID_factura igual a 1 y despues hago un
y recupero el id_factura asi id_factura:= IBQuery1.FieldByName('id_factura').AsInteger; y ya despues en la tabla detalle hafo un loop
el problema es que siempre lo he hecho asi. inserto el encabezado de la factura despues pregunto a la BD por el ID de la factura que recien ingrese y como no se su id hago el query que revise si esta existe con la serie , el folio. el rfcdel emisor, del cliente. existe alguna forma de saber el ID o el campo que yo quiera de una registro recien ingresado. por mi aplicacion. en este caso me quiero evitar la query para saber si existe una facuta con la serie , el folio. el rfcdel emisor, del cliente. y capturar la respuesta. usando los componentes ibexpress. o algun otro muchas gracias por su atencion. |
#2
|
||||
|
||||
En la ayuda de firebird comentan lo que estas buscando, exactamente en el texto README.returning.txt que se encuentra al instalar firebird en la carpeta: ...\Firebird\doc\sql.extensions
parte del texto
|
#3
|
||||
|
||||
Cita:
Además, sólo es viable en Firebird 2.1 y 2.5. Saludos, |
#4
|
||||
|
||||
Y todavía Marteens nos puede ayudar ....
Lo más sencillo es usar generadores en Firebird.
Te pongo un extracto del libro de Marteens perteneciente a la Cara Oculta de Delphi 6 (puedes descargarlo en pdf de muchas webs) , que aunque no es actual te puede servir perfectamente. Generadores Los generadores (generators) son un recurso de InterBase para poder disponer de valores secuenciales, que pueden utilizarse, entre otras cosas, para garantizar la unicidad de las claves artificiales. Un generador se crea, del mismo modo que los procedimientos almacenados y triggers, en un fichero script de SQL. El siguiente ejemplo muestra cómo crear un generador: create generator CodigoEmpleado; Un generador define una variable interna persistente, cuyo tipo es un entero de 32 bits. Aunque esta variable se inicializa automáticamente a 0, tenemos una instrucción para cambiar el valor de un generador: set generator CodigoEmpleado to 1000; Por el contrario, no existe una instrucción específica que nos permita eliminar un generador. Esta operación debemos realizarla directamente en la tabla del sistema que contiene las definiciones y valores de todos los generadores: delete from rdb$generators where rdb$generator_name = 'CODIGOEMPLEADO' Para utilizar un generador necesitamos la función gen_id. Esta función utiliza dos parámetros. El primero es el nombre del generador, y el segundo debe ser la cantidad en la que se incrementa o decrementa la memoria del generador. La función retorna Procedimientos almacenados y triggers 245 entonces el valor ya actualizado. Utilizaremos el generador anterior para suministrar automáticamente un código de empleado si la instrucción insert no lo hace: create trigger NuevoEmpleado for Empleados active before insert as begin if (new.Codigo is null) then new.Codigo = gen_id(CodigoEmpleado, 1); end ^ Al preguntar primeramente si el código del nuevo empleado es nulo, estamos permi-tiendo la posibilidad de asignar manualmente un código de empleado durante la in-serción. Los programas escritos en Delphi con el BDE tienen problemas cuando se asigna la clave primaria de una fila dentro de un trigger utilizando un generador, pues el registro recién insertado “desaparece” según el punto de vista de la tabla. Este problema se presenta sólo cuando estamos navegando simultáneamente sobre la tabla. Para no tener que abandonar los generadores, una de las soluciones consiste en crear un procedimiento almacenado que obtenga el próximo valor del generador, y utilizar este valor para asignarlo a la clave primaria en el evento BeforePost de la tabla. En el lado del servidor se programaría algo parecido a lo siguiente: create procedure ProximoCodigo returns (Cod integer) as begin Cod = gen_id(CodigoEmpleado); end ^ En la aplicación crearíamos un componente spProximoCodigo, de la clase TStoredProc, y lo aprovecharíamos de esta forma en uno de los eventos BeforePost o OnNewRecord de la tabla de clientes: procedure TmodDatos.tbClientesBeforePost(DataSet: TDataSet); begin spProximoCodigo.ExecProc; tbClientesCodigo.Value := spProximoCodigo.ParamByName('COD').AsInteger; end; De todos modos, si la tabla cumple determinados requisitos, podemos ahorrarnos trabajo en la aplicación y seguir asignando la clave primaria en el trigger. Las condicio-nes necesarias son las siguientes: 1 La tabla no debe tener columnas con valores default. Así evitamos que el BDE tenga que releer la fila después de su creación. 2 Debe existir un índice único, o casi único, sobre alguna columna alternativa a la clave primaria. La columna de este índice se utilizará entonces como criterio de ordenación para la navegación. 3 El valor de la clave primaria no nos importa realmente, como sucede con las claves artificiales. Las tablas de referencia que abundan en toda base de datos son un buen ejemplo de la clase de tablas anterior. Por ejemplo, si necesitamos una tabla para los diversos valores del estado civil, probablemente la definamos de este modo: create table EstadoCivil ( Codigo integer not null primary key, Descripcion varchar(15) not null unique, EsperanzaVida integer not null ); create generator EstadoCivilGen; set term ^; create trigger BIEstadoCivil for EstadoCivil active before insert as begin Codigo = gen_id(EstadoCivilGen, 1); end ^ En Delphi asociaremos una tabla o consulta a la tabla anterior, pero ordenaremos las filas por su descripción, y ocultaremos el campo Codigo, que será asignado automáti-camente en el servidor. Recuerde, en cualquier caso, que los problemas con la asigna-ción de claves primarias en el servidor son realmente problemas de la navegación con el BDE, y nada tienen que ver con InterBase, en sí. Cuando estudiemos DataSnap, además, veremos cómo estos problemas se resuelven con elegancia en este sistema. NOTA IMPORTANTE En cualquier caso, si necesita valores únicos y consecutivos en alguna columna de una tabla, no utilice generadores (ni secuencias de Oracle, o identidades de MS SQL Server). El motivo es que los generadores no se bloquean durante las transacciones. Usted pide un valor dentro de una transacción, y le es concedido; todavía no ha termi-nado su transacción. A continuación, otro usuario pide el siguiente valor, y sus deseos se cumplen. Pero entonces usted aborta la transacción, por el motivo que sea. La consecuencia: se pierde el valor que recibió, y se produce un "hueco" en la secuencia. |
#5
|
|||
|
|||
ok. muchas gracias.
parece que el unico componente que soporta RETURNING es el IBDAC de devart IBDAC http://www.crlab.com/ibdac/ InterBase Data Access Components. Comercial, actively developed. Provides extensive functionality and support for new Firebird 2 features like the EXECUTE STATEMENT and the RETURNING clause. A trial version is available for download. http://www.firebirdfaq.org/faq8/ ¿ahora bien. mi metodo esta bien. o puede ser mejorado? por que lo que escribio Antoniov no le entendi. para lo de hacer claves unicas. o compuestas. que entiendo seria casi lo mismo pero de forma distinta. de que hago el insert y luego al db hago un query se de select la serie , el folio. el rfcdel emisor, del cliente. y capturo la respuesta. como se que los datos son unicos. por la serie y el folio. y el rfcdelemisor y del receptor. yo confio en que sera la factura que recien estoy ingresando. muchas gracias por su atencion. |
#6
|
||||
|
||||
FIBPlus también lo soporta en su tiempo me acuerdo haberlo implementado, pero, luego use generadores, como comentan lineas arriba.
Implementación: mediante un procedimiento obtener el valor del generador en el evento OnBeforePost y luego trabajar con dicho valor según lo requerido, cabe recalcar que uso ClientDataSet en la capa de Entidad y bueno en la Logica uso solo referencias. El procedimiento para obtener el valor del generador es:
O de forma general:
Donde: P_TABLE: Es es nombre de la tabla d_sys_relation_name: dominio tipo varchar(31) d_sys_field_name: dominio tipo varchar(31) El nombre del generador como se puede observar es "S_" || "El nombre del campo", en mi caso siempre es el que se define primero en la tabla (rdb$field_id = 0). Bueno y otro requerimiento es que exista el generador, sino el procedimiento devolverá cero. Uso Firebird 2.5, pero creo que también esta disponible para la versión 2.1 |
|
|
Temas Similares | ||||
Tema | Autor | Foro | Respuestas | Último mensaje |
Duplica registro en ClientDataSet maestro-detalle | Josepo | Conexión con bases de datos | 8 | 07-05-2013 11:59:09 |
Maestro detalle con firebird e IBExpress | edenis | Conexión con bases de datos | 1 | 13-10-2006 19:09:08 |
Maestro detalle solo muestra un registro | jandres | Varios | 2 | 10-06-2006 13:11:49 |
InserciÓn De Registro Con Maestro-detalle | perillan | Conexión con bases de datos | 5 | 23-10-2005 12:15:23 |
Cancelar un registro en maestro/detalle... | uper | Firebird e Interbase | 1 | 15-09-2004 18:56:40 |
|