PDA

Ver la Versión Completa : Generadores¡¡¡¡


mosorio
14-06-2003, 12:05:41
Hola compañeros,

Tengo un inconveniente con los generadores, bueno extactamente con ellos no sino con la obtención del valor. Cuando ejecuto la sentencia sql para obtener el último, y asignarlo en el campo, tarda casi un segundo o mas en mostrarse y se nota la tardanza, el cídogo que utilizo es:


sqlGenId.Close;
sqlGenId.CommandText := '';
sqlGenId.CommandText := 'Select gen_id('+ NombreGen +', 0) Id '+ 'from RDB$DATABASE';
sqlGenId.Open;

result := sqlGenId.FieldValues['ID'] + 1;
sqlGenId.Close;


Este es el ejemplo que he encontrado en la webde Ian, también se de las consecuencias que pueden haber al restringir las tablas del sistema en las nuevas versiones de Firebird.

Lo que necesito es saber si hay algún procedimiento más optimo, se que este lo es, pero alguno donde no se note el refresco, he intentado desactivar los controles pero no me asigna el valor en el campo o no lo muestra.
Como pueden ver estoy utilizando dbexpress.
Si hago un procedimiento almacenado donde pueda obtener el dato, no se si sea más veloz u optimo, si es así, tendría que hacer uno por cada tabla que necesite incrementar.

Agradezco la ayuda de antemano.

PD: Disculpen si no he contstado o dado consejo alguno de los dif. hilos, pero estoy contra el reloj con este proyecto. Prometo colaborar cuando vaya finalizando, espero sea pronto.

Gracias :rolleyes:

mosorio
14-06-2003, 14:12:41
Hola delphoros!

Creo que esta vez me contestaré a mi duda, y espero le sirva a todos los que han tenido y tendrán esta misma.
He utilizado un procedimiento almacenado en la BD sencillo que ejecuta un generador:


create procedure Gen_Codigo
returns (Id Integer) as
begin
Id = Gen_Id(<NombreGenerador>, 1);
end^

:. NombreGeberador es el generador creado para cada una de las tablas o id que necesitan incremento.


Ahora en el programa Delphi, en el datamódulo se inserta un componente SP sin asignarle el procedimiento almacenado, esto para reutilizarlo con los otros.

Se crea una function para ejecutar el SP y retornar el valor:


function TdmPrg.EjecutarGenerador(NombreGen: String): Integer;
begin
spGenerador.Close;
spGenerador.StoredProcName := NombreGen;
spGenerador.ExecProc;

Result := spGenerador.Params[0].AsInteger;
end;

procedure TdmPrg.cdsTipoIVAAfterInsert(DataSet: TDataSet);
begin
cdsTipoIVA.FieldByName('IDTIPOIVA').AsInteger := EjecutarGenerador('GEN_IDTIPOIVA');
end;



Y en CDS en el evento despues de insertar capturamos el valor para ser asignado al componente dbe que ha sido enlazado con el datasource.
Ahora la respuesta es mucho más rápida y no se nota la asignación.
Yo estoy trabajando en el mismo pc y tengo instalado un SO de servidor, esta tardanza era bastante preocupante ya que en el mismo pc daba el retardo, no quería imaginar cuando se hicieran las pruebas en red a otros pc.
Lógico esta que al cancelar una inserción se perderá el consecutivo, pero esto lo controlaré más adelante en la misma BD realizando los controles de actualiación en cascada y otras cositas que he estado viendo en el motor FireBird, IB y el libro de La cara Oculta de Delphi 4

Gracias y espero les sirva.

AbcXxx
17-06-2003, 17:45:41
Para no perder el consecutivo yo hago lo siguiente:
Hice un "trigger before insert" y es ahi donde ejecuto el

Id = Gen_Id(<NombreGenerador>, 1);

y tengo entendido que solo se va a ejecutar cuando realmente se este insertando en la tabla

el codigo me queda asi (aunque no lo se poner entre "quote:")

CREATE TRIGGER SETFOLIO FOR ORDENGAS
ACTIVE BEFORE INSERT POSITION 0
as
begin
new.folio = gen_id(folio_gen,1);
end

y como usualmente nesecitamos saber cual es la clave para regresarla a la pantalla o imprimirlo, yo lo soluciono con un procedimiento que es el encargado de insertar los datos a la tabla:


ALTER PROCEDURE APPENDORDEN (CARRO SMALLINT,
PLACAS VARCHAR(10),
KILOMETROS INTEGER,
SUCURSAL INTEGER,
CHOFER VARCHAR(30),
AUTORIZO VARCHAR(30),
TIPO VARCHAR(10))
RETURNS (FOLIO INTEGER)
AS
begin
insert into ordengas(carro, placas,kilometros,sucursal,chofer,autorizo,tipo)
values (:carro,:placas,:kilometros,:sucursal,:chofer,:autorizo,:tipo);
folio=gen_id(folio_gen,0);
end

como veran, este es el procedimiento que llamo cuando inserto un nuevo registro; le paso los valores validados previamente para que halla menos posibilidades de error y el procedimiento al tratar de insertar los datos en la tabla se dispara el trigger SETFOLIO el cual aumenta el generador y me asigna el valor en el campo folio, para despues retornar el valor de el numero de folio desde el mismo procedimiento...

...Como se pone el codigo entre rayitas??? :D

kinobi
17-06-2003, 18:05:49
Hola,

Posteado originalmente por AbcXxx
y tengo entendido que solo se va a ejecutar cuando realmente se este insertando en la tabla

cierto, pero si haces un rollback el registro no quederá insertado (cosa lógica), pero el generador no volverá a su antiguo valor, por tanto sí es posible que queden huecos en la secuencia. Recuerda que los generadores no están bajo el control transaccional.

Regla a no olvidar con generadores: un generador tocado (incrementado o disminuido su valor) no es posible deshacer el cambio con rollback.

Otra regla: Los generadores pueden garantizar valores enteros únicos, pero no necesariamente en secuencia (sin huecos).

En cierta forma son conceptos excluyentes, puedes crear un mecanismo que genere valores unicos, pero sin la garantía de secuencia (los generadores), y al contrario: puedes crear un mecanismo que garantice la secuencia, pero entonces no garantizarás la unicidad (este mecanismo no lo tiene implementado InterBase). Vamos, que los dos a la vez no es posible.

Saludos.

AbcXxx
17-06-2003, 18:34:45
cierto, pero si haces un rollback el registro no quederá insertado (cosa lógica), pero el generador no volverá a su antiguo valor, por tanto sí es posible que queden huecos en la secuencia. Recuerda que los generadores no están bajo el control transaccional.

Tienes toda la razon (como de costumbre), y si, lo que hago inmediatamente despues de ejecutar el procedimiento que inserta, hago un commit, aunque tambien se que esto no me garantiza que se realize con exito...

En cierta forma son conceptos excluyentes, puedes crear un mecanismo que genere valores unicos, pero sin la garantía de secuencia (los generadores), y al contrario: puedes crear un mecanismo que garantice la secuencia, pero entonces no garantizarás la unicidad (este mecanismo no lo tiene implementado InterBase). Vamos, que los dos a la vez no es posible.

definitivamente me quedo con el primer metodo

Hasta pronto...

p.d. se nota que ya se usar las citas???:D