Ver Mensaje Individual
  #4  
Antiguo 29-08-2011
Avatar de Antoniov
Antoniov Antoniov is offline
Miembro
NULL
 
Registrado: ago 2011
Ubicación: Tenerife
Posts: 42
Reputación: 0
Antoniov Va por buen camino
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.
Responder Con Cita