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 de Alonso Jarrín Solís
1
1
![Alonso Jarrín Solís](http://blob.todoexpertos.com/avatars/sm/alonso197.jpg?v=44)
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.
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.
- Compartir respuesta
- Anónimo
ahora mismo
![](/content/images/user_nophoto_small.png)