Control de errores

Quisiera saber si es posible que me expliques con uno o dos ejemplos una rutina para controlar los errores que se presentan cuando se utilizan los desencadenantes (integridad referencial). La verdad es que no tengo mucha experiencia en el manejo del vfp 9.0 y te agradecería que me aconsejaras cual es la mejor opción.

1 respuesta

Respuesta
1
Bueno para comenzar en Visual FoxPro y en cualquier otro gestor de base de datos los errores que se producen cuando falla el desencadenante se deben a estas situaciones que son las más comunes:
1. Estás insertando un registro en la tabla secundaria con un valor clave que no existe en la tabla primaria (aquí está restringida la inserción y por lo tanto es un error de inserción).
2. Estás actualizando en la tabla primaria el valor clave de un registro que tiene registros relacionados en la tabla secundaria (aquí está restringida la actualización, y por lo tanto es un error de actualización, ésta solo podrá realizarse cuando en la tabla secundaria no existan registros relacionados tanto física como lógicamente).
3. Estás eliminando en la tabla primaria un registro que tiene registros relacionados en la tabla secundaria (aquí está restringida la eliminación, y por lo tanto es un error de eliminación, ésta solo podrá realizarse cuando en la tabla secundaria no existan registros relacionados tanto física como lógicamente).
En Visual FoxPro cuando falla el desencadenante se produce el error número 1539, una vez que se haya notificado que se ha producido este tipo de error, usted deberá llamar a la función Aerror() que crea una matriz de variables de memoria con información relativa al error más reciente de Visual FoxPro u ODBC.
El elemento número 5 de la matriz, si ha fallado un desencadenante (error 1539), contiene uno de los siguientes valores numéricos:
1 - El desencadenante Insert falló (inserción).
2 - El desencadenante Update falló (actualización).
3 - El desencadenante Delete falló (eliminación).
Para poder controlar este tipo de errores la rutina más común es esta:
En el evento click de un botón de comando o en el evento de un formulario que sea para guardar cambios se escribe un código parecido a este:
Local lcError, lcArrayError[AERRORARRAY]
lcError = !Tableupdate(.T.)
If lcError Then
  If Aerror(lcArrayError) > 0
    Thisform.Error(lcArrayError[1])
  Endif
  Else
     Go (Recno()) && Forzar la actualización de cualquier relación.
Endif
Return !lcError
Para el caso de que sea u formulario de uno a varios, deberá iniciar una transacción para actualizar todas las tablas a las que se le hayan hecho cambios y en el caso de que en alguna de ellas falle la actualización ya sea por una falla de desencadenante o cualquier otro tipo de error, entonces deberá revertir los cambios con Rollback, por ejemplo en el siguiente código se actualiza la tabla primaria y luego se actualizan las tablas secundarias las cuales están almacenados sus nombres en una matriz personalizada, este código es ideal para formularios de tipo factura o formularios de introducción de datos de uno a varios, este código va en un evento personalizado de un formulario:
Local lcError, lcArrayError[AERRORARRAY]
Begin Transaction
lcError = (Txnlevel() = 0)
If !lcError
  If !lcError Then
    * Si no han cambiado los datos en la tabla primaria, no se disparará
    * el desencadenante a menos que lo forcemos.
    Select (This.ParentTable)
    If GetFldState(-1) = Replicate("1", Fcount() + 1)
      =SetFldState(2,2)
    EndIf
    lcError = !Tableupdate(.T.) && Actualizar tabla primaria.
    If !lcError
       For i = 1 To Alen(This.AChildTables, 1)
          Select (This.AChildTables(i,1))
          If GetNextModified(0, (This.AChildTables(i,1))) <> 0
            lcError = !Tableupdate(.T.)
          Endif
          If lcError
            Exit
          EndIf
      EndFor
    Endif
    If !lcError Then
       End Transaction
       Select (This.ParentTable)
       Else
          RollBack
          =Aerror(lcArrayError)
          This.Error(lcArrayError[1], lcArrayError[2])
          This.RefreshForm()
     EndIf
   EndIf
EndIf
Return !lcError
Ahora para responder a tu pregunta y con un ejemplo específico te explicaré cómo se tratan los errores producidos por desencadenantes, supongamos que tenemos un formulario de facturación en el cual tiene las tablas respectivas como Clientes, encabezado_factura, detalle_factura, vendedor, etc, debidamente relacionadas y con la integridad referencial establacida, se debe ingresar el NIT del cliente en la tabla encabezado_factura, pero teniendo en cuanta que dicha tabla no registra el NIT de un cliente que no esté registrado en la tabla clientes, entonces se procederá a dar una solución ya sea registrando el respectivo cliente o verificando los datos del mismo así:
En el evento click de un botón guardar iría un código como el siguiente:
Local lcError, lcArrayError[AERRORARRAY]
Begin Transaction
lcError = (Txnlevel() = 0)
If !lcError
  If !lcError Then
    * Si no han cambiado los datos en la tabla primaria, no se disparará
    * el desencadenante a menos que lo forcemos.
    If Alias() <> "FACTURA_ENCABEZADO"
       Select Factura_encabezado
    Endif     
    If GetFldState(-1) = Replicate("1", Fcount() + 1)
      =SetFldState(2,2)
    EndIf
    lcError = !Tableupdate(.T.) && Actualizar tabla primaria.
    If !lcError
      Select Detalle_factura
      If GetNextModified(0, "Detalle_factura") <> 0
         lcError = !Tableupdate(.T.)
      Endif
      If lcError
        Exit
      EndIf
    Endif
    If !lcError Then
       End Transaction
       Select Select Factura_encabezado      
       Else
          RollBack
          =Aerror(lcArrayError)
          Thisform.Error(lcArrayError[1], lcArrayError[2])
          Thisform. Refresh()
     EndIf
   EndIf
EndIf
Return !lcError
En el caso de que el usuario intentó ingresar el NIT de un cliente que no está registrado en la tabla clientes, entonces esto se resuelve así:
En el evento Error del Formulario escribiríamos un código cómo el siguiente:
=AError(lcAerror)
Do Case
    Case nError = 1539 && Falló el desencadenante en este caso el desencadenante Insert.
    If MessageBox("El cliente no existe. ¿Desea registrarlo?, 48, "Error") = 6 && Sí
      If lcAerror(5) = 1 && Falló el desencadenante Insert.
        This.RegistrarCliente() && Un evento para registrar el cliente.
      EndIf
      Else
         This.TxtNitCliente.Value = "" && Si el usuario se equivocó entonces corrige el error.
     Endif
    Case nError = 1582
        Resolver el problema
    Case nError = .... y así para resolver otros errores
        Resolver el problema
EndCase
Con esto espero haber sido claro de cómo se resuelve estos errores de desencadenantes.
Nota: si se hace una aplicación que se conecta a otras bases de datos, es decir, mediante ODBC, debes consultar los códigos de error de los desencadenantes en la respectiva documnetación de la base de datos de origen para reemplazar los códigos de error por sus respectivos valores.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas