Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   autonumerico en base al maestro (https://www.clubdelphi.com/foros/showthread.php?t=9429)

jzginez 22-04-2004 23:36:48

autonumerico en base al maestro
 
Hola a todos tengo estas tres tablas en firebird 1.5

CREATE TABLE TESTILO (
ID VARCHAR(15) NOT NULL,
DESCRIPCION VARCHAR(40),
FECHA DATE DEFAULT 'now',
ID_MATERIAL INTEGER,
IMAGEN IMAGENES /* BLOB SUB_TYPE 0 SEGMENT SIZE 80 */,
PRECIO FLOAT,
PRODUCDESEADA INTEGER,
EFICIENCIA INTEGER,
CANTIDAD INTEGER,
ID_CLIENTE INTEGER
);

CREATE TABLE TOPERACIONES (
ID INTEGER NOT NULL,
AVERVIATURA VARCHAR(10),
DESCRIPCION VARCHAR(40),
FECHA DATE DEFAULT 'now',
PAGOSEMANA FLOAT,
ID_TIPOMAQ VARCHAR(10),
ID_DEPTO INTEGER,
MINUTAJE TIME,
MINTSEXA FLOAT,
MINTOCIO FLOAT,
TAREAPORHORA FLOAT,
TAREAPORDIA FLOAT,
PAGOOPER FLOAT
);

CREATE TABLE TOPERESTILO (
ID INTEGER NOT NULL,
ID_ESTILO VARCHAR(15),
ID_OPER INTEGER
);

el campo ID de la tabla toperaciones es autonumerico con su generator y su trigger y funciona bien, la tabla toperestilo es un maestro detalle ya que por id_estilo puede haber una o mas operaciones pero necesito que el campo id empiese a numerarse desde 1 cada que ID_Estilo cambia de valor y así despues poder saber cuantas veces la operación uno fue la primera en realizarse, cuantas fue la tercera etc.

espero me puedan ayudar y sobretodo me entiendan

jachguate 23-04-2004 00:13:42

para esto no podes usar un generador. Es mejor que asignes los números desde tu aplicación... pues el generador partirá de 1, y no volverá "automáticamente" a este valor....

jzginez 23-04-2004 03:49:33

Master, nuevamente mil gracias.

oye ya entrados en la exprimidera de cerebros siempre he escrito mis trigger como viene en la ayuda de interbase es decir entre los comandos

SET TERM !! ;
Create trigger............
.
.
.
SET TERM; !!


pero nunca he encontrado para que son me podrias esplicar su uso.

gracias

jachguate 23-04-2004 07:44:27

esto, segun tengo entendido, ya ha sido superado en la versión 1.5 de firebird. Básicamente, es debido a que el programa cliente no era capaz de recnoocer el final del trgger/stored procedure, debido a que el caracter de fin de sentencia (;, que es el que normalmente se usa para delimitar las sentencias en un script, también se utiliza para delimitar las sentencias dentro del trigger.

Si no haces la llamada a set term... ocurrirá que, en un script como este:

Código:

  Create trigger mitrigger
    Active before insert on tabla
  AS
  Begin
    Update OtraTabla
        Set campo = campo + New.campo
      where llave = New.llave;
    Update OtraTabla2
        Set campo = campo + New.campo
      where llave = New.llave;
  End;

El sistema creerá que la sentencia termina despues del primer punto y coma (justo despues del primer update) y asi la lanzará al pharser de SQL; evidentemente incompleta, con lo que daría un error que provocaría la terminación anormal de la ejecución del script.

Al cambiar el caracter de terminación de las sentencias por !!, por ^ o por cualquier otro delimitador que no sea el punto y coma, se consigue determinar donde termina efectivamente la sentencia... evitando estos problemas.

Hasta luego.

;)

sanxpue 27-04-2004 02:42:39

:confused:
Código PHP:

para esto no podes usar un generador
Es mejor que asignes los números desde tu aplicación... 
pues el generador partirá de 1
y no volverá "automáticamente" a este valor.... 

Si usas un Procedimiento almacenado podras hacer eso lo que dices

Código:

Create Procedure  INICIA_GENERADOR
As
DECLARE VARIABLE
GEN INTEGER;
Begin
  GEN = GEN_ID(generador,0);
  WHILE (GEN > 0) DO
    GEN = GEN_ID(generador,-1);
END

Funciona como debe de funcionar

jachguate 27-04-2004 02:53:38

Pero vos estas asumiendo el caso en que no habrá necesidad de insertar un nuevo registro detalle para un registro ya existente... o que no habrá dos usuarios ingresando información concurrentemente. En cualquiera de estos dos casos, el proceso fallará generando claves duplicadas (suponiendo que la clave es clavemestro+contadordetalle)

En el post anterior, cometí el error de usar el verbo poder, cuando debi usar el deber. "Para esto no debes usar un generador"...

en fin, son vicios de lenguaje. :p

Hasta luego.

;)

sanxpue 27-04-2004 17:19:07

Pues no le veo
 
Pues no le veo problema, puesto que podemos crear su generator para cada usuario diferente, en tiempo de ejecucion y asi como su Stored Procedure, y como dices el problema seria clavemaestro+clavecontador, pero como tu dices tambien se toparia con lo mismo, supongamos que sea un punto de venta y el pastelito x tiene la clave 1 y al mismo tiempo llegan dos clientes en diferentes cajas y los cajeros chechan el pastelito 1 primero ahi tambien se repetiria.. no crees¡¡¡¡, entonces la clave primaria deberia ser clavemaestro+clavecontador+numerodecaja

jachguate 27-04-2004 17:54:51

Cita:

Empezado por sanxpue
Pues no le veo problema, puesto que podemos crear su generator para cada usuario diferente, en tiempo de ejecucion y asi como su Stored Procedure, y como dices el problema seria clavemaestro+clavecontador,

Creo que estas asumiendo muchas cosas sobre una aplicación de la que ambos no tenemos idea. Esto podria funcionar en unos casos y no en otros... asi que, para poder llegar a una conclusión en un tiempo prudencial, que sea útil a quien pregunta y al resto de la comunidad, propongo que nos basemos en el caso mas general posible.

Cita:

Empezado por sanxpue
pero como tu dices tambien se toparia con lo mismo, supongamos que sea un punto de venta y el pastelito x tiene la clave 1 y al mismo tiempo llegan dos clientes en diferentes cajas y los cajeros chechan el pastelito 1 primero ahi tambien se repetiria.. no crees¡¡¡¡

Es que en este caso, el registro maestro no seria el producto, sino el encabezado de envío, factura (o cualquier otra figura equivalente) que se está generando.

Yo no me refiero a que se duplique el número del contador, que eso es precisamente lo que se busca.

Pero te voy a poner un ejemplo... suponiendo el caso ya expuesto del punto de venta.

Estado Actual:

Caja1: Esperando cliente
Caja2: Esperando cliente
Caja3: Cajero en tiempo de comida

Secuencia de sucesos:

  • caja1Inicio de transaccion (factura 10) Supongo que en este momento se reiniciaria el generador, ingresa 3 lineas (10,1), (10,2), y (10,3)
  • caja2Inicio de transaccion (factura 11) Se reinicia el generador, ingresa 1 linea (11,1)
  • caja1ingresa otra línea: error: clave duplicada! (10,2)
  • caja2Ingresa otra línea (11,3) warning: queda un agujero en el contador Esto dependiendo del tipo de aplicación real, puede o no tener importancia.
  • Caja 3Regresa de comer, y le piden que agregue un item a la factura 3, que ya tenia grabados 75 items... error: seguramente habrá clave duplicada (3, 4) (o a estas alturas ya es una loteria)

Esto es para un caso sencillo con solo 3 usuarios concurrentes... pero en la práctica puede llegar a ser mucho mas complejo.

Si puede crearse un generador por usuario, dependerá que un usuario quiera usar solamente una instancia de la aplicación. El crear uno por terminal... limitará a una instancia por terminal...

En fin, es mi apreciación personal, que en este caso, es mejor establecer otro método para generar este tipo de secuencias... o bien cambiar un poco la forma de pensar, y tener un único generador para todos los detalles.

La mejor forma de hacerlo, será diferente de acuerdo a las especificaciones de cada aplicación, y corresponderá a su analista definir un criterio.

Hasta luego.

;)

sanxpue 27-04-2004 18:34:10

Asi es como dices
 
Asi es como dices estamos asumiendo que estamos haciendo el programa nosotros, jejeje y no deberiamos.. pero nada mas te explico mi idea va

Antes de tu estado actual falta el prender las cajas
  • Prendes Caja1 crea generador GCaja1
  • Prendes Caja2 crea generador GCaja2
  • Prendes Caja3 crea generador GCaja3

Estado Actual:
  • Caja1: Esperando cliente
  • Caja2: Esperando cliente
  • Caja3: Cajero en tiempo de comida

Secuencia de sucesos:
  • caja1 Inicio de transaccion (factura 10) Supongo que en este momento se reiniciaria el generador, ingresa 3 lineas (10,1), (10,2), y (10,3) (tomando los numeros del Generador GCaja1)
  • caja2 Inicio de transaccion (factura 11) (Se reinicia el generador, aqui no se reinicia el generado) ingresa 1 linea (11,1) (Tomando los numeros del Generador GCaja2)
  • caja1 ingresa otra línea (: error: clave duplicada! (10,2) aqui no hay error ya que meteria) (10,4) (del generador GCaja1)
  • caja2 Ingresa otra línea (11,2) (warning: queda un agujero en el contador tampoco ¡¡¡hay warning¡¡)

Esto dependiendo del tipo de aplicación real, puede o no tener importancia.

Ahora lo que pones a continuacion, asi como tu dices y como yo digo lo que debemos hacer es saber cual es el ultimo numero de item que metio.


Caja 3 Regresa de comer, y le piden que agregue un item a la factura 3, que ya tenia grabados 75 items...
Entonces ahi seguimos usando la potencia de los procedimientos almacenados, (de todos modos hay que consultar cuantos tiene) consultando cuantos items tiene y vamos aumentando el GCaja3 hasta 75 (en este caso)
entonces entraria el 76
(error: seguramente habrá clave duplicada (3, 4) (o a estas alturas ya es una loteria))


weno ya vez alguna vez nos han de servir estas ideas no crees, y como tu dices todo empezo por el uso de nuestro lenguaje

saludos :D

jachguate 27-04-2004 21:50:41

ahora dejemos la aplicación de caja... y vamos a una aplicación donde, por cualquier motivo, un usuario entra dos veces al sistema... cómo resolverias esto???

sanxpue 27-04-2004 21:55:38

compañero...
 
si te das cuenta estoy creando generadores por maquina no por usuario, osease el usuario puede tener 3 maquinas al mismo tiempo..

resuelto..

jachguate 27-04-2004 22:23:45

oh.. entonces supongamos que un usuario abre dos instancias del programa en la misma máquina... :eek:

sanxpue 27-04-2004 22:31:26

Pues ...
 
Pues que programador mas chafa si deja abrir otra instancia, por que eso se ve a leguas que puede pasar¡¡¡

ahora preguntame

y si llega el raton miguelito y se mete al servidor y no deja avanzar o pone en cero el generator


¿¿pero haber que pasaria si le da post y le falta un dato que no debe de ser nulo, el generador avanza, como resolverias esto??
para que vuelva a regresar al que se quedo

jachguate 27-04-2004 23:15:07

El punto a resaltar, es que, evidentemente hay muchas formas de resolver el problema... algunas funcionarán en unos casos y no en otros... y como lo dije antes, será al analista a quien le corresponde determinar el mejor camino en base a los requerimientos de su aplicación. No hay una regla general aplicable a todos los casos.

Hasta luego.

;)

jzginez 30-04-2004 23:43:43

hola para empezar una disculpa pues no habia podido contestarles ya que me habia quedado sin conección a internet, voy a checar bien sus sugerencias y probar cuales son los pro y contra de acuerdo al sistema que estoy haciendo y les platicare despues en que quedo.

Gracias

jzginez 21-05-2004 00:42:08

Hola amigos les comento que para el campo autonumerico en base al maestro por la urgencia en el uso lo programe en mi aplicación pero hoy ya con calma modifique mi triger de la siguiente forma:
Código SQL [-]
CREATE TRIGGER TOPERESTILO_BI FOR TOPERESTILO
ACTIVE BEFORE INSERT POSITION 0
AS
declare variable contador integer;
BEGIN
  IF (NEW.ID IS NULL) THEN
    NEW.ID = GEN_ID(GEN_TOPERESTILO_ID,1);
  select count(id) from toperestilo where id_estilo = new.id_estilo into :contador;
  new.orden = :contador + 1;
END

y las prueba que hasta el momento llevo va funcinando bien

sanxpue 21-05-2004 02:43:40

Que bien que..
 
Que bien que has hecho las pruebas..

Eso si funciona bien si no tienes un indice que no sea el autoincremento..
cuando te manda el error de un indice duplicado se genera el autoincremento y se generara tambien tu contador :confused:


La franja horaria es GMT +2. Ahora son las 17:46:43.

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