PDA

Ver la Versión Completa : Control de excepciones


gorsan
08-03-2008, 10:38:59
Hola a todos.
Aunque, creo, que lo que les voy a plantear es algo muy simple para la mayoria, para mi es complejo porque lo desconozco pero me encantaria poder manejar bien estas situaciones.

Trabajo con IBX6 y Delphi 7.
En el diseño de la base de datos tengo definidas algunas excepciones:

CREATE EXCEPTION "MAL_DNI" 'DNI incorrecto. Debe estar comprendido entre 1 y 99999999.';
CREATE EXCEPTION "MAL_N_IDEN" 'Número incorrecto. Debe estar comprendido entre 1 y 99.';

entre otras.
Mi pregunta es ¿como lanzo una excepcion definida en la base de datos desde el código delphi?
Hasta ahora un codigo parecido al siguiente me bastaba:

procedure TForm1.BotonGrabarClick(Sender: TObject);
begin
try
//las acciones a proteger
except
//el lanzamiento de la excepcion en caso de error
ShowMessage('Asignación incorrecta o repetida.');
raise;
end;
end;


Pero cuando en la tabla donde se añade el nuevo registro hay varios campos con la restriccion UNIQUE, necesito saber:
1 cual es el que da el error para lanzar una u otra
2 como lanzo las excepciones definidas por mi en la base de datos.

Muchas gracias por su tiempo.

Lepe
08-03-2008, 10:49:04
Son dos cosas totalmente separadas.

Crea un trigger before Post en la tabla, verificas allí si el dni está comprendido entre el rango y si no lo está lanzas la excepción.

La filosofía es contraria a lo que piensas. Ahora te olvidas hacer las validaciones en el boton grabar en delphi, directamente dejas pasar los datos a la base de datos, y en los triggers adecuados, el SGBBDD hará saltar la excepción que tu quieras:

Trigger (hecho de memoria....):

Create trigger Check_Valores for tabla before update active position 0
as
begin
if (new.CampoDNI < 1 or new.CAmpoDNI > 99999999) then
exception MAL_DNI;
end;

Al saltar la excepción, verás en delphi un MessageBox con el texto de la excepción.

PD: el usuario, a veces no sabe el dni para dar de alta el registro, deberías dejarle introducir un cero para esos casos especiales. Si no.... ya te lo pedirán ;).

Para estos 2 casos, yo no crearía una excepción, sino un "check constraint". Revisa la documentación de Firebird/IB.

Saludos

gorsan
08-03-2008, 11:13:55
Muy amable por tu respuesta y respecto a lo del check constraint tienes razon. Lo estudiare.
Gracias Lepe.

gorsan
08-03-2008, 12:18:43
Pero ¿como escribo el trigger si la excepcion se produce por la contravencion de un valor UNIQUE?

eduarcol
08-03-2008, 14:07:48
Se supone que al definir un campo como unico el manejador de base de datos se encarga de lanzar esa excepcion

gorsan
08-03-2008, 14:34:36
Ya. El sistema maneja todas las excepciones pero yo lo que quiero es lanzar mi propia excepcion para que el usuario la vea tal como yo quiero que la vea y lanzarle el mensaje que yo planifique. Da mas sensacion de control.

eduarcol
08-03-2008, 15:00:54
Ya. El sistema maneja todas las excepciones pero yo lo que quiero es lanzar mi propia excepcion para que el usuario la vea tal como yo quiero que la vea y lanzarle el mensaje que yo planifique. Da mas sensacion de control.

Eso que tu propones yo lo hice con el BDE, capturando la excepcion desde delphi, aqui esta el codigo para que te hagas una idea. Pero en Firebird he dejado que el manejador de base de datos se encargue de todo eso, menos trabajo para el programador.

try
Result := True;
T.Active := False;
T.Exclusive := False;
T.DatabaseName := cRutaDatos;
T.TableName := NT;
T.IndexName := Indices;
T.Active := True;
except
on E: EDBEngineError do
begin
ErrorCode := E.Errors[0].ErrorCode;
case ErrorCode of
DBIERR_SYSFILEOPEN,
DBIERR_SYSFILEIO,
DBIERR_SYSCORRUPT,
DBIERR_NOCONFIGFILE,
DBIERR_CFGCANNOTWRITE,
DBIERR_CFGMULTIFILE,
DBIERR_REENTERED,
DBIERR_CANTFINDIDAPI,
DBIERR_CANTLOADIDAPI,
DBIERR_CANTLOADLIBRARY,
DBIERR_TEMPFILEERR,
DBIERR_MULTIPLEIDAPI,
DBIERR_SHAREDMEMCONFLICT:
msgError( msErrorSistema + NT );
DBIERR_LOCKED,
DBIERR_UNLOCKFAILED,
DBIERR_FILEBUSY,
DBIERR_DIRBUSY,
DBIERR_FILELOCKED,
DBIERR_DIRLOCKED,
DBIERR_ALREADYLOCKED,
DBIERR_NOTLOCKED,
DBIERR_LOCKTIMEOUT,
DBIERR_GROUPLOCKED,
DBIERR_LOSTTBLLOCK,
DBIERR_LOSTEXCLACCESS,
DBIERR_NEEDEXCLACCESS,
DBIERR_RECGROUPCONFLICT,
DBIERR_DEADLOCK,
DBIERR_ACTIVETRAN,
DBIERR_NOACTIVETRAN,
DBIERR_RECLOCKFAILED,
DBIERR_OPTRECLOCKFAILED,
DBIERR_OPTRECLOCKRECDEL,
DBIERR_ENLISTFAILED,
DBIERR_NETFILELOCKED,
DBIERR_NETMULTIPLE:
msgError( msTablaBloqueada + NT );
DBIERR_FILECORRUPT: msgError(msTablaCorrupta + NT);
DBIERR_INDEXCORRUPT: msgError(msIndiceCorrupto +NT);
DBIERR_READERR: msgError(msErrordeLectura +NT);
DBIERR_DIRNOACCESS: msgError(msSinAccesoaDirectorio + NT);
DBIERR_FILENOACCESS: msgError(msSinAccesoaArchivo + NT);
DBIERR_NOMEMORY: msgError(msSinMemoria + NT);
DBIERR_OPENTBLLIMIT: msgError(msMuchasTablasAbiertas + NT);
DBIERR_NOSHAREDMEMORY: msgError(msSinMemoriaCompartida + NT);
DBIERR_INVALIDFILENAME: msgError(msNombreArchivoIncorrecto + NT);
DBIERR_NOSUCHINDEX: msgError(msNombreIndiceIncorrecto + NT);
else msgError(msErrorDesconocido + E.Message);
end;
Result := False;
end;
end;