Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Trucos (https://www.clubdelphi.com/foros/forumdisplay.php?f=52)
-   -   Más trucos con generadores (https://www.clubdelphi.com/foros/showthread.php?t=80605)

dec 30-06-2006 18:06:50

Más trucos con generadores
 
Ahora que ya sabe como crear y destruir un generador nos queda conocer cómo podemos obtener el valor actual del generador. ¡Elemental, Watson!, pensará usted. Hasta el alcalde de mi pueblo sabe que existe la función gen_id, que recibe un nombre de generador y un incremento, lo aplica al generador y devuelve el valor del mismo. Casi siempre el generador se utiliza en triggers o procedimientos como los siguientes:

Código Delphi [-]
create trigger AsignarCodigoFormaPago for FormasPago
   active before insert position 0 as
begin
   if (new.Codigo is null) then
      new.Codigo = gen_id(FormaPagoGen);
end!

create procedure DameUnNumero returns(Codigo integer) as
begin
   Codigo = gen_id(OtroGenerador, 1);
end!

Ante tanta sabiduría me siento obligado a preguntarle algo: ¿qué valor devuelve gen_id, el que tenía el generador antes del incremento, o el valor posterior? Pues es el valor posterior al incremento el que se retorno. Claro, no esperaba otra cosa de usted...

¿Y cómo puedo obtener el valor actual del generador, pero sin modificarlo? La primera vez que me lo preguntaron, contesté algo que aún me avergüenza recordar:

Código Delphi [-]
// ¡¡¡MUY MALO!!!
create procedure ValorActual returns(Codigo integer) as
begin
   Codigo = gen_id(OtroGenerador, 1);
   Codigo = gen_id(OtroGenerador, -1);
end!

¿Funcionar? Creo que sí, pero funciona a lo bestia. Con más experiencia sobre mis espaldas, ahora me doy cuenta de que el siguiente procedimiento es más racional:

Código Delphi [-]
create procedure ValorActual returns(Codigo integer) as
begin
   Codigo = gen_id(OtroGenerador, 0);
end!

De todos modos sigue existiendo un problema. Supongamos que estamos desarrollando una herramienta de diseño, al estilo de SQL Explorer, o de Marathon. En tal caso, no tendremos a mano un procedimiento como el anterior para cada uno de los generadores de la base de datos. Pero el problema no es grave: gen_id es una función como cualquier otra (aunque causa un efecto secundario), y puede colocarse en una cláusula select. Inmediatamente me viene a la mente la tabla Dual de Oracle: una tabla predefinida que siempre contiene una sóla fila. Si tuviésemos esta tabla en InterBase, nos bastaría ejecutar la siguiente instrucción para conocer el valor actual de un generador:

Código SQL [-]
// ¡¡¡NO FUNCIONA, LA TABLA Dual ES DE ORACLE, NO DE INTERBASE!!!
select gen_id(OtroGenerador, 0) from Dual

Bien, no existirá Dual en InterBase, pero sí tenemos la tabla interna del sistema RDB$DATABASE, que hasta donde conozco, siempre tiene una sola fila. Entonces podemos utilizar esta variante:

Código SQL [-]
// VARIANTE CORRECTA
select gen_id(OtroGenerador, 0) from RDB$DATABASE

En realidad, SQL Explorer utiliza este otro truco:

Código SQL [-]
// VARIANTE DE SQL EXPLORER
select distinct gen_id(OtroGenerador, 0) from RDB$GENERATORS

Por supuesto, el resultado del select anterior ¡siempre tiene una sola fila!.


La franja horaria es GMT +2. Ahora son las 01:28:50.

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