Evitar que se agreguen registros duplicados en una base de datos access

He estado buscando cómo evitar que se agregue un registro duplicado en access y lo que vi se aproxima pero mi nivel no logra hacerlo funcionar para mi necesidad (solo lo hace en un campo).

La cuestión es que tengo tres campos que siempre "trabajan" juntos. Paso a detallar. Mi Tabla Expedientes tiene los campos Carátula, Número y Año. Los tres son de tipo Texto (tamaño 4 - 6 y 2 caracteres respectivamente).

El campo carátula se repite mucho al igual que el año, pero el que es irrepetible en un mismo año es el campo número.

Ejemplo, tengo muchos 2406 (que es carátula) pero el número 23674 se da una sola vez por año de modo que puede haber 2406 - 23674 - 12 y también 2406 - 23674 - 14 donde sólo cambia el año y también 5100 - 23674 - 12 que sólo cambia la carátula.

Esta base manejará muchos datos con el correr del tiempo y sería necesario que si coloco un expediente repetido me de un mensaje de que ya está ingresado. Pero tienen que coincidir los tres campos.

Agrego que también me puede ingresar un expediente de años anteriores (ejemplo del 2005 o de 2010), es decir, no son siempre los del año en curso (esto facilitaría las cosas).

Lógicamente el aviso se tiene que dar cuando se completaron los tres campos que por un orden de tabulación y de armado del formulario son los tres primeros datos que se ingresan.

Bueno, disculpen las molestias y desde ya un agradecimiento

1

1 respuesta

Respuesta
1

Tabaré: Según yo lo interpreto, el ejemplo que pones se contradice con el texto anterior>>

... Pero el que es irrepetible en un mismo año es el campo número.

Que puede haber 2406 - 23674 - 12 y también 2406 - 23674 - 14

... Y también 5100 - 23674 - 12

En cualquier caso mi sugerencia es la siguiente: Añade un campo a la Tabla que se llame por ejemplo TextoTestigo, y un Control en el Formulario con el mismo Nombre, que puede estar oculto.

Al entrar el último dato de los tres, que voy a suponer que es el Número

Private Sub Numero_BeforeUpdate(Cancel As Integer)
Dim CadenaComprueba As String
CadenaComprueba = Me.Numero & Me.Año
If Nz(DCount("TextoTestigo","TuTabla";"TextoTestigo = '" & CadenaComprueba & "'"),0) >0 Then
MsgBox "Esta cadena ya está en la Tabla........" & vbCrLf & "Repasa la entrada e intenta de nuevo", vbCritical, "FALTAN DATOS EN LAS HORAS"
        DoCmd.CancelEvent
        Me!Numero.Undo
Else
Me.TextoTestigo = CadenaComprueba
End If
End Sub

Naturalmente que deberías incluir alguna linea que asegure que el año ya tiene un valor.

Ya me contarás. Saludos >> Jacinto

Hola Jacinto, un gusto para mí y una molestia para vos...

A ver si me explico; los expedientes tienen una carátulas que generalmente es la misma porque se generan en la misma repartición (oficina) en mi caso son casi siempre 2406 pero si vienen de otro lado pueden ser 5100 ó 2436 ó etc.

El número es correlativo pero empieza cada año, de modo que arranco en el 1 y puedo llegar al 9599 o más o menos (por eso le puse 6 cifras en el diseño de la tabla).

De modo que tendría por ejemplo: desde el 2406 - 1 - 16   al   2406 - 9599 - 16 o al que llegue.

Lo que aclaro es que no puedo tener otro 2406 - 9599 - 16 pero sí un 2406 - 9599 - 15 ó del año que imagines. También puedo tener un 5100 - 9599 - 16

De modo que lo que necesito es que no se repita todo ese número compuesto por los tres campos.

Se puede dar: 2406-9599-16  ó  2406-9599-15  ó  5100-9599-16  ó  2406-9510-16, pero lo que no debe suceder es que los tres campos ya hayan sido registrados en conjunto.

Yendo a la práctica, en mi formulario comienzo con un nuevo expediente y coloco la carátula = 2406 (hasta ahí nada), paso al otro campo y escribo el número = 9599 (sigue sin pasar nada) y paso al siguiente campo y escribo el año = 16. Recién aquí me tiene que salir la advertencia que ese todo ese combo (carátula, número, año) ya está ingresado, ya que todo esos números corresponden a UN expediente que no puedo tenerlo cargado dos veces. 

Ya se que me dirías, bueno, que busquen a ver si fue cargado, pero nunca falta el que no lo hace y lo ingresa como nuevo.

Por ahí leí que se podría definir un indice con los tres campos de valores únicos pero mi clave principal es un Id autonumérico y no comprendo cómo sería.

Bueno, espero que te hay aclarado lo que no supe expresar anteriormente.

Un abrazo.

Tabaré: Mi sugerencia sigue siendo la misma, a excepción de que en lugar de trabajar con dos Campos/Controles lo hagas con los tres. En el Código que te cito a Continuación el Campo a añadir le he puesto el Nombre de: TextoExp y el Control de Formulario, (Oculto o no) con el mismo nombre.

Private Sub Año_BeforeUpdate(Cancel As Integer)
Dim CadenaExpediente  As String
If Not IsNull(Me.Caratula) And Not IsNull(Me.Numero) And Not IsNull(Me.Año) Then
    CadenaExpediente = Me.Caratula & Me.Numero & Me.Año
    If Nz(DCount("TextoExp","TuTabla";"TetoExp = '" & CadenaExpediente & "'"),0) >0 Then
        MsgBox "Esta cadena ya está en la Tabla........" & vbCrLf & "Repasa la entrada e intenta de nuevo", vbCritical, "DATO YA INTRODUCIDO"
        DoCmd.CancelEvent
        Me.Undo
        Me.Caratula.SetFocus
    Else         
        Me.TextoExp = CadenaExpediente
    End If
Else
    MsgBox “Has de rellenar antes la Carátula, El Numero y el Año”,vbCritical, “ERROR”
End If
End Sub

Como me has comentado que el orden de entrada de datos era : Caratula, Numero y Año, he puesto el código en el Evento BeforeUpdate del último, en este caso Año.

No te olvides activar el Procedimiento si copias directamente el código.

Y por descontado que para llenar los datos de ese Campo que añadas, tendrás que hacer una Consulta de Actualización,(la puedes hacer con el asistente), haciendo el Campo TextoExp = La union de los otros tres campos.

Mis saludos >> Jacinto

¡Gracias! 

Rapidísima la respuesta.

Voy a probar y te cuento como me ha ido

Saludos

Amigo, está casi cocinado. Lo que mandaste lo acomodé, hice la consulta y casi todo Ok

Pequeño detalle, si agrego un expediente ya ingresado, sale el MsgBox. Cuando le doy aceptar sale un nuevo MsgBox (2108) que dice:

"Debe guardar el campo antes de ejecutar la acción IrAControl, el método GoToControl o el método SetFocus"

Además, me tira otro error en el módulo que registra quién hizo los cambios (MdlComparaCambios).

Borré esa línea del proceso 

Me.Caratula.SetFocus

y se libera pero ahora queda el foco en el año, no vuelve a Carátula.

 No sería algo grave ya que no queda nada registrado, o sea, se queda todo el formulario en blanco.

Lo que sí aumenta el Id Clave Principal que es autonúmerico. Hice varias pruebas seguidas ingresando expedientes ya ingresados, no guarda ningún dato pero en la tabla el autonumérico salta del último guardado al nuevo. No me molesta ya que creo que eso no "engorda" la base de datos.

Es como si se hubieran eliminado esos registros. Como sigo probando para ver si salta algún error ya voy por el registro 23 (salta del 14 al 23). 

Un abrazo

Tabaré: Había escrito sobre la marcha, y si que debes sacar esa línea.

He remirado el resto, y lo veo correcto, aunque a éstas horas ya no vea mucho.

Es posible que el error en el Modulo que recojas los cambios, se deba al nuevo campo insertado, que debas declararlo. Solo es una opinión sin mucho fundamento.

Mis saludos >> Jacinto.

No te preocupes Jacinto, me has ayudado muchísimo. 

Si luego ves algo me lo comunicás, pero no es un gran problema.

Bueno, un abrazo y muchas gracias

Hola Jacinto, te molesto por la siguiente consulta: la BD que estoy terminando las la pienso dividir posta que los que la usen tengan sólo el front-end. 

Pero si por alguna razón tengo que hacer alguna modificación tanto en una tabla o en un formulario, cómo se hace?

Ya que me quedan la tablas en un lugar y formularios en varias pc. 

Y además, las copias de seguridad las debo hacer sólo de las tablas que sin las que se actualizan, o de todo en conjunto?

Gracias

Tabaré: La cópia de seguridad, basta que la hagas del BackEnd.

Modificacones: De los FrontEnd, en tu PC modificas lo que quieras y después si quieres mandas un Zip a los usuarios, para que ellos mismos lo actualicen y si alguno no sabe hacerlo.

Si eres administrador de la Red >> Lo modificas tu en Remoto

Si no lo eres >> Pues igual pero in situ.

Del BackEnd: Lo natural es que hagas pocas modificaciones, pero si lo necesitas, lo mas aconsejable bajo mi punto de vista (aunque esto va de acuerdo a la forma de hacer de cada uno), es que documentes bien las modificaciones, aproveches un horario de inactividad o provoques una parada en los procesos de esa BD y hagas las modificaciones directamente en el BackEnd del Servidor. Copia previa Imprescindible. Mis saludos >> Jacinto

Si, cuando haga la división es porque consideré que estaba todo lo necesario, aunque nunca se sabe, sólo el tiempo lo aclara. Por eso la duda respecto a las modificaciones.

Ya hice una prueba en mi pc y vi que las tablas quedan con unas flechitas. 

Otra duda, conviene hacer compactación de la BD todos los días cuando se "sale".? O puede generar algún daño

Tabaré: en éste tema de Compactar la Bd ada vez que se cierra tiene defensores y detractores. Yo siempre compacto al cerrar. Tengo la muesca activada.

Si quieres generar una pregunta sobre el tema, es posible que recibas más de una respuesta y así sopesas otros puntos de vista y lo que argumentan.

En mi opinión el único inconveniente que tiene es que consume un poco más de tiempo al cerrarse, pero aligera la BD de todos los "Apuntes" Temporales que va haciendo.

También dependerá de la máquina que tengas, del Sistema Operativo, etc.

Mis saludos >> Jacinto

¡Gracias! 

Bueno Jacinto fuiste muy amable y paciente.

Me has ayudado muchísimo y te agradezco la atención.

Espero no tener que molestarte, aunque sea por un tiempo.

Abrazos

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas