Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > SQL
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 19-02-2010
mjjj mjjj is offline
Miembro
 
Registrado: mar 2007
Posts: 652
Poder: 18
mjjj Va por buen camino
Ordenes entrelazadas

Hola gente del foro, una preguntita.

Desarrolle una aplicación para generar ordenes de compra, lo cual queda registrado en 2 tablas, COMPRAS Y DETCOMPRAS.

Utilizo Delphi 2006, Firebird 2.0 y cmponentes Interbase.

Esto funciona de la siguiente manera, el usuario al presionar el boton de nueva orden, el software se conectada a la BD, y guarda un registro los campos usuario y fecha. Gracias a un generador y un trigger le asigno un correlativo unico.

Hasta aqui todo bien, el problema surge cuando tengoq ue comenzar a ingresar el detalle de la orden. Para saber a cual numero de orden tengo que asignarle los detalles ingresados, justo después de agregar el registro en la tabla COMPRAS, realizo una consulta a esa misma tabla preguntando por el máximo númoer de orde.

El asunto es que si fuera un solo usuario, esto funcionaria de maravilla, pero me ha ocurrido que mas de 1 usuario ha realizado la operación al mismo tiempo y ocurre que el detalle de las ordenes se mezclan.

Existe una mejor idea de como resolver esto?

Espero me puedan ayudar.

Saludos
Responder Con Cita
  #2  
Antiguo 19-02-2010
Avatar de jafera
jafera jafera is offline
Miembro
 
Registrado: may 2007
Ubicación: Llagostera (Girona)
Posts: 582
Poder: 18
jafera Va por buen camino
Tienes que tener un campo en el detalle compra que sea el codigo de la compra.

En cada new record del detalle le dices que el id de este detalle es el id de la compra, pero en un campo que no sea el id del detalle.

Ejemplo

Cabecera de la compra
ID_COMPRA FECHA ID_CLIENTE.......
Aquí el ID_COMPRA puede ser autoincrementable

Detalle de la compra
ID_DETALLE ID_COMPRA REFERENCIA PRECIO......
Aqui el ID_DETALLE puede ser autoincrementable pero ni el ID_COMPRA que se lo pasas de la cabecera.

Espero te sirva

Josep
Responder Con Cita
  #3  
Antiguo 19-02-2010
mjjj mjjj is offline
Miembro
 
Registrado: mar 2007
Posts: 652
Poder: 18
mjjj Va por buen camino
Asi es exactamente como lo tengo desarrollado.

El código se ejecutada de la siguiente manera:
Se presiona el button para una nueva orden.

El codigo del botton es asi:

Código Delphi [-]
begin
 
ibtransaction1.active:=true;
ibsql1.close;
ibsql1.sql.add('insert into compras (fecha, usuario) values (current_date, :usuario)');
ibsql1.parambyname('usuario').asstring := usuario;  // el usuario que este conectado
ibsql1.execquery,
 
ibtransaction1.commit;
 
ibquery1.close;
ibquery1.sql.clear;
ibquery1.sql.add('select max(noc) noc from compras');
ibquery1.open;
 
noc := ibquery1.fieldbyname('noc').asinteger;
end;


El campo NOC es autoincremental, pero al parecer cuando 2 usuarios tratan de realziar una nueva orden se duplicada los numeros y no entiendo bien que es lo que ocurre.

Es por eso que me dirijo a usted para resolver esto, o mejor aún una mejor forma de realizar esto.

Como lo haría usted??

Espero me puedan ayudar.
Responder Con Cita
  #4  
Antiguo 19-02-2010
mjjj mjjj is offline
Miembro
 
Registrado: mar 2007
Posts: 652
Poder: 18
mjjj Va por buen camino
Existe la opción se enviarle el NOC incrementado al usuario que lo ingreso, esto para evitar tener que consultar cual es el máximo NOC.

La idea sería que el mismo motor de BD, cada vez que se insertara un registro en la tabla COMPRAS, devolviera solamente al usuario que realizo el ingreso del registro el número NOC incrementado.

De esta forma utilizo ese correlativo para ingresar los registros en la tabla DETCOMPRAS, en el campo NOC.

Se podrá hacer esto?
Valdrá la pena desarrollarlo?
La teoría como dice que se debiese realizar?

Espero me puedan ayudar.

Saludos
Responder Con Cita
  #5  
Antiguo 19-02-2010
Avatar de jafera
jafera jafera is offline
Miembro
 
Registrado: may 2007
Ubicación: Llagostera (Girona)
Posts: 582
Poder: 18
jafera Va por buen camino
Yo en casos así, lo que hago es buscar el ultimo valor de la tabla y le sumo 1 cuando doy de alta el registro.

Josep
Responder Con Cita
  #6  
Antiguo 19-02-2010
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.289
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Hemos hablado otras veces de este tema.

La primera opciçon es intentar hacerlo utilizando transacciones. Deberías probar a realizar la inserción y consulta en la misma transación (tal vez debas jugar con el Isolation Level de la transacción).

La segunda la uso para SQL Server, desconozco si en FB hay algo similar (algun experto en FB que nos lo confirme). En SQL Server existe una opción de para saber cual es el último AUTOINCREMENTAL insertado. Utilizandolo puedes crear un Stored Procedure que inserte en registro y a la vez devuelva el valor del autoincremental (utilizando parámetros).
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #7  
Antiguo 19-02-2010
Avatar de movorack
[movorack] movorack is offline
Miguel A. Valero
 
Registrado: feb 2007
Ubicación: Bogotá - Colombia
Posts: 1.346
Poder: 20
movorack Va camino a la famamovorack Va camino a la fama
Creo que con un procedimiento almacenado harias lo que quieres, por lo menos asi lo he hecho yo... al procedimiento almacenado le paso tanto los datos generales de la orden como los detalles con el array de elementos.

el mismo procedimiento te creará la orden y los detalles en las respectivas tablas dentro de la misma transacción evitandote los problemas actuales.
__________________
Buena caza y buen remar... http://mivaler.blogspot.com
Responder Con Cita
  #8  
Antiguo 19-02-2010
mjjj mjjj is offline
Miembro
 
Registrado: mar 2007
Posts: 652
Poder: 18
mjjj Va por buen camino
gracias movorack, voy a investigar esto de los procedimientos almacenados.

Me podrías exponer un ejemplo del codigo que debiese utilizar para realizar esto.


Adicionamente, los datos que el usuario introsuzca, estoy hablando de por ejemplo el cliente, detalles de la orden... estos antes de ser enviados al procedimiento para ser almacenados, donde los tendre que guardar? en variables locales?

Espero me puedas acercar un ejemplo y asi poder entenderlo mejor.

Saludos
Responder Con Cita
  #9  
Antiguo 19-02-2010
Avatar de movorack
[movorack] movorack is offline
Miguel A. Valero
 
Registrado: feb 2007
Ubicación: Bogotá - Colombia
Posts: 1.346
Poder: 20
movorack Va camino a la famamovorack Va camino a la fama
Por alguna razón no puedo insertar la imágen pero bueno... http://lh4.ggpht.com/_IuT93QvTKI0/S3...endepedido.png

el anterior es el formulario... todo está en edits y variables locales... los elementos de la orden están en un TStringGrid y cuando solicito crear la orden armo la consulta.

se me olvidaba un pequeño detalle... yo uso Postgres no firebird. aún así este es el codigo del procedimiento...

Código SQL [-]
CREATE OR REPLACE FUNCTION pedidos.fn_req(
  prm_cyp_id character varying,
  prm_usr_id integer,
  prm_art_det_id integer[],
  prm_req_art_cant integer[],
  prm_o_art character varying[],
  prm_t_compra integer
)  RETURNS integer AS
$BODY$
DECLARE
  var_req_id INTEGER;
  var_curtime time;
  var_cant integer;
  var_cont integer;
  _estd_xfact varchar;
  _estd_pndte varchar;
  _estd_xent varchar;
  _estd_sql varchar;
  _compra_nrml int4;
  _compra_aprv int4;
BEGIN
  --valores por defecto...
  var_curtime := current_time;
  _estd_xfact := 'E9';
  _estd_pndte := 'E1';
  _estd_xent  := 'E6';
  _compra_nrml := 0;
  _compra_aprv := 1;

  --Estado inicial del estado
  _estd_sql := _estd_xfact;
  if prm_t_compra = _compra_aprv then
    _estd_sql = _estd_pndte;
  end if;

  --Insercion de requisicion
  INSERT INTO pedidos.requisiciones(req_time, cyp_id, usr_id, estd_id)
    VALUES(var_curtime, prm_cyp_id, prm_usr_id, _estd_sql);

  --obtener el ID de la insercion
  SELECT INTO var_req_id req_id
  FROM pedidos.requisiciones
  WHERE
    req_date = current_date
    AND req_time = var_curtime
    AND cyp_id = prm_cyp_id
    AND estd_id = _estd_sql
    AND usr_id = prm_usr_id;

  -- cantidad de articulos en detalle
  var_cant := ARRAY_DIM(1, prm_art_det_id);

  -- Insercion del detalles
  FOR i IN 1..var_cant LOOP
    _estd_sql := _estd_xfact;
    if prm_t_compra = _compra_aprv then
      _estd_sql = _estd_pndte;
    end if;

    INSERT INTO pedidos.req_art(req_id, art_det_id, req_art_cant, estd_id, req_art_orgn)
      VALUES (var_req_id, prm_art_det_id[i], prm_req_art_cant[i], _estd_sql, prm_o_art[i]);
  END LOOP;  

  RETURN var_req_id;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;
__________________
Buena caza y buen remar... http://mivaler.blogspot.com
Responder Con Cita
  #10  
Antiguo 23-02-2010
mjjj mjjj is offline
Miembro
 
Registrado: mar 2007
Posts: 652
Poder: 18
mjjj Va por buen camino
Se me ocurre otra idea, es posible detectar la transacción y el usuario que inserto el registro en la tabla COMPRAS, esto con el fin de devolverle a ese usuario el campo con el registro autoincrementado?

Así de esta forma, y dentro de la misma transacción insertar el detalle de la orden de compra... ya que necesito el campo aotoincrementado de la tabla COMPRAS, para relacionar estas últimas.


No se si será una buena idea, pero me gustaría saber si se puede hacer esto.
Investigue con el componente TIBEvent, que se puede detectar movimientos en la BD, pero no se si asosiarlo a un usuario específico.

Bueno, les dejo planteada la idea, se alguien tiene alguna mejor, me gustaría mucho leerla.

Slaudos
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Como contar ordenes de impresion? JuanErasmo C++ Builder 2 25-01-2006 20:35:17


La franja horaria es GMT +2. Ahora son las 21:57:18.


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
Copyright 1996-2007 Club Delphi