Ver la Versión Completa : Evitar un Key Violation
sitrico
14-01-2004, 15:05:15
Buenas, Estoy retocando una aplicación y quisiera verificar ANTES DE QUE OCURRA la validez de una clave, me explico:
Visitando los foros encontré que una de las maneras de manejar la excepción del Key Violation era:
Try
db.Post;
Except
Mensaje....
End;
Ahora bien, manejarlas de esa manera me obligaría a crear un bloque Try..Excep en cada post de la aplicación. Preferiría usar los eventos de la base de datos OnPostError o mejor OnBeforePost para validar la clave antes de que se genere la excepción. Tengo la dificultad adicional de que parte de la base de datos está filtrada y hay claves ocultas.
¿ Existe alguna función como Function IsValidKey(Registro o clave):Boolean (o algo así) que permita llamar a la BDE para que se verifique la validez de la clave ?
El código debe ser algo así:
Evento On BeforePost
If Not(IsValidKey(Registro acual)) Then
Begin
// Mensaje de clave duplicada
Abort; // pero debe seguir el insert o edit
End;
cadetill
14-01-2004, 15:10:23
Existir, no existe, que yo sepa, lo que puedes hacer es en BeforePost lanzar una query sobre la tabla y en el where poner la clave y mirar si devuelve o no registros
o bien utilizar el evento OnPostError y mirar el código de error que devuelve para saber si es debido a un key violation
eduarcol
14-01-2004, 16:18:06
No se si te entendi mal, pero lo que tu pides es algo tan facil como crear una funcion donde haces el bloque try ... except para la tabla que le pases por parametro, y al momento de grabar no llamas al post sino a la funcion que te devolvera true si se ejecuto o false si fallo, en el except debes capturar el error en un objeto EDBEngineError
te doy un ejemplo
function Mi Grabado(MiTabla: TTable): Boolean
begin
try
T.Post;
except
on E: EDBEngineError do
begin
ErrorCode := E.Errors[0].ErrorCode;
case ErrorCode of
//distintos casos de error(busca la ayuda)
end
end
end
al llamarla funcionara algo asi
if MiGrabado(Tabla) then
Me parece la solucion mas facil
delphi.com.ar
14-01-2004, 16:21:58
O... conociendo la PK puedes preguntar si no existe algún registro con estos datos, esto evitaría que se produzca el error.
Saludos!
roman
14-01-2004, 16:35:31
Me gustaría agregar, respecto de la pregunta original, que en mi opinión los errores de violación de acceso no deben tratarse mediante bloques try-except. Son errores graves que puden dejar inestable a la aplicación o a la pc y es mejor revisar qué los causa y retocar el código para que no sea así (verificar que los punteros u objetos no sean nil, que no referenciemos índices de arreglos inválidos, etc,)
Por favor olviden esto. Me confundí entre "Access Violation" y "Key Violation"
// Saludos
marcoszorrilla
14-01-2004, 16:58:21
Aquí tienes los códigos más interesantes de error y un ejemplo de como manipular el "KeyViol", yo lo que hago es definir un Procedimiento y le llamo desde cualquier postError de cualquier tabla para evitar la repetición del mismo código.
const
eKeyViol = 9729;
eRequiredFieldMissing = 9732;
eForeignKey = 9733;
eDetailsExist = 9734;
eSqlGralerror = 13059;
implementation
{$R *.DFM}
procedure TForm1.Table1PostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction);
begin
if (E is EDBEngineError) then
if (E as EDBEngineError).Errors[0].Errorcode = eKeyViol then
begin
Application.MessageBox('Imposible dar alta ese registro ya existe','Atención',mb_Ok +
mb_IconQuestion);
Abort;
end;
end;
Un Saludo.
sitrico
16-01-2004, 21:45:11
Gracias a todos, opté por la solución de marcoszorrilla porque validar usando un query antes de cada post no debe ser muy bueno para el rendimiento ;-)
lroblesco
16-03-2005, 03:40:04
Saludos
tengo un problemilla cuando se repiten las claves,
Aquí tienes los códigos más interesantes de error y un ejemplo de como manipular el "KeyViol", yo lo que hago es definir un Procedimiento y le llamo desde cualquier postError de cualquier tabla para evitar la repetición del mismo código.
const
eKeyViol = 9729;
eRequiredFieldMissing = 9732;
eForeignKey = 9733;
eDetailsExist = 9734;
eSqlGralerror = 13059;
implementation
{$R *.DFM}
procedure TForm1.Table1PostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction);
begin
if (E is EDBEngineError) then
if (E as EDBEngineError).Errors[0].Errorcode = eKeyViol then
begin
Application.MessageBox('Imposible dar alta ese registro ya existe','Atención',mb_Ok +
mb_IconQuestion);
Abort;
end;
end;
Un Saludo. Saben pongo el codigo como este, y me salta la excepcion, y en el debugger option escojo que no se detenga en las excepciones. Me sale un error mas o menos asi "Los cambios solicitados en la tabla.......' que puedo hecer? manejo una BD Access 2000 gracias
marcoszorrilla
16-03-2005, 14:25:18
Aclarar que la rutina que yo facilité en su día es para el BDE, Paradox fundamentalmente, por lo cual no servirá para Access.
Un Saludo.
Ing Harry
01-06-2005, 18:06:47
Saludos
Tengo Un Problema Al Validar Llaves Primarias. Resulta Que Yo Hice Una Aplicacion Que Se Alimenta A Partir De Archivos Planos. Yo Valido Usando Una Consulta Que Toma Cada Linea Y La Consulta En La Tabla, En Caso De Que Su Llave Este Duplicada, El Sistema La Actualiza Con Los Demas Campos, En Caso Contrario Crea Un Nuevo Registros Con Estos Datos. El Problema Es Que Al Cargar Un Archivo Con Muchos Registros El Sistema Se Me Pone Lento. Estoy Convencido Que El Problema Radica En La Forma De Validar. Que Me Recomiendan Ustedes Hacer Para Mejorar El Rendimiento.
Agradezco La Atencion.
Atentamente
Ing Harry :d :d :d
vBulletin v3.6.8, Derechos ©2000-2013, Jelsoft Enterprises Ltd.