FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
|||
|
|||
Manejo de errores en Master Detail
Hola Amigos nuevemente estoy recurriendo a ustedes para que me ayuden a solucionar este problema:
Tengo Firebird 1.5 con Delphi 7 IbTransaction1. Params read_commited rec_version nowait La Tabla Detalle (ValesDetalle) proviene de un stringgrid y la Tabla Maestro(ValesMaestro) proviene de datos de cliente mas la suma del campo Total de ValesDetalle. En las inserciones de la Tabla Maestro y la Tabla Detalle no tengo problemas, ellos estan cuando tengo que actualizar la Tabla StockMaestro del campo Cantidad de la Tabla Detalle. Para esto lo hago con una Stored Procedure que debe manejar las stes. situaciones: Si no hay stock debe hacer un rollback Si hay un lock_conflict deberia repetir la procedure hasta hacer el update Si hay cualquier otro error debe hacer un rollback. La Procedure CREATE PROCEDURE ACTUALIZA_VALESDETALLE( VID_VALE VARCHAR(12), VID_PRODUCTO VARCHAR(12), VCANTIDAD DECIMAL(7,2), VDESCRIPCION VARCHAR(40), VVALORUNITARIO NUMERIC, VTOTAL NUMERIC) RETURNS ( FLAG SMALLINT) AS DECLARE VARIABLE V_STOCK DECIMAL(7,2); BEGIN INSERT INTO VALESDETALLE ( ID_VALE, ID_PRODUCTO, CANTIDAD, DESCRIPCION, VALORUNITARIO, TOTAL ) VALUES ( :VID_VALE, :VID_PRODUCTO, :VCANTIDAD, :VDESCRIPCION, :VVALORUNITARIO, :VTOTAL ); SELECT EXISTENCIA FROM STOCKMAESTRO WHERE ID_PRODUCTO = :VID_PRODUCTO INTO :V_STOCK; IF (:V_STOCK >= :VCANTIDAD) THEN BEGIN UPDATE STOCKMAESTRO SET EXISTENCIA = :V_STOCK - :VCANTIDAD WHERE ID_PRODUCTO = :VID_PRODUCTO; FLAG = 0; END ELSE EXCEPTION NO_STOCKDETALLE; WHEN EXCEPTION NO_STOCKDETALLE DO BEGIN FLAG = 1; END WHEN GDSCODE lock_conflict DO BEGIN ¡¡¡¡NO SE QUE HACER!!! END WHEN ANY DO BEGIN FLAG = 1; END END ^ Y el procedimiento en Delphi /////// For a := 1 to stringGrid1.RowCount - 1 do begin with IbStoredProc1 do begin Close; IbStoredProc1.StoredProcName := 'ACTUALIZA_VALESDETALLE'; ParamByName('VID_VALE').AsString := VCodigo; ParamByName('VID_PRODUCTO').AsString := StringGrid1.Cells[4,a]; ParamByName('VCANTIDAD').AsFloat := StrToFloat(StringGrid1.Cells[0,a]); ParamByName('VDESCRIPCION').AsString := StringGrid1.Cells[1,a]; ParamByName('VVALORUNITARIO').AsInteger := StrToInt(StringGrid1.Cells[2,a]); ParamByName('VTOTAL').AsInteger := Total; Prepare; ExecProc; VFlag := ParamByName('FLAG').AsInteger; end; if VFlag = 1 then Break; end; Label6.Caption := IntToStr(VFlag); if VFlag = 1 then begin IbTransaction1.RollBack; s := StringGrid1.Cells[0,a] + ' ' + StringGrid1.Cells[1,a]; MessageDlg('Registro ' + s + ' no tiene stock suficiente',mtError,[mbOk], 0); end else IbTransaction1.Commit; end; end; En base a lo planteado, que debo hacer para manejar el lock_conflict Muchas gracias. |
#2
|
||||
|
||||
Exception conflicto
Es decir, te creas una excepción y desde ahí la lanzas, Firebird deshace los cambios de forma automática según el caso: - Si es un SP de SELECT, puede haber varios SUSPEND, solo se deshace los cambios desde el último SUSPEND; - Si es un SP ejecutable, no debe haber SUSPEND, por tanto se deshace el SP al completo. Deberias olvidarte del Flag, y especificar el mensaje directamente en la excepción creada.
__________________
Si usted entendió mi comentario, contácteme y gustosamente, se lo volveré a explicar hasta que no lo entienda, Gracias. |
#3
|
|||
|
|||
Hola Amigos, un saludo Lepe. Muy agradecido de tu sugerencia.
pero me gustaria profundizar mas sobre el tema. Como se desprende del codigo Delphi la procedure Actualiza_ValesDetalle se repite tantas veces como lineas tenga el stringgrid que alimenta la tabla Detalle (ValesDetalle). Por lo tanto si ocurre un error del tipo lock_conflict es porque el Parametro nowait no permitio actualizar la transaccion ya que habia que esperar que terminara otra en proceso. Pues bien, lo que yo pienso es que si sucede un lock_conflict lo logico seria poder repetir la procedure ya que al hacerlo no existiria la condicion de lock_conflict y me permitiria hacer el commit de toda la transaccion. Por eso insisto como puedo hacer que este codigo me haga repetir la instruccion de update: WHEN GDSCODE lock_conflict DO BEGIN ¡¡¡¡NO SE QUE HACER!!! END Ojala haya alguna sugerencia. Muchas gracias. |
|
|
|