Relación entre tablas en Access

Tengo una duda al respecto a la relación entre tablas en Access 2010.
Tengo dos tablas, tabla1 y tabla2. También tengo una tabla3 la cual esta relacionada con tabla2 pero no creo que afecte a mi problema, pero por si acaso la escribo. La relación es la siguiente:
tabla1(oferta, ..., recursos)
TABLA2(ID_OFERTA, ID_COMPONENTE, ...)
tabla3(componente, ... )
Teniendo una relación 1 a infinito entre RECURSOS (tabla1) e ID_OFERTA (tabla2) y una relación infinito a 1 entre ID_COMPONENTE (tabla2) y COMPONENTE (tabla3)
En el formulario1 almaceno los datos referentes a la tabla1, sin embargo no se me almacena el numero metido en OFERTA en ID_OFERTA de la tabla2 a pesar de estar relacionadas, ¿es esto normal?
He intentado hacer chanchullos metiendo DoCmd. RunSql "Insert Into... En el botón de guardar que tengo en mi formulario1 sin embargo me da error al compilar por problema entre claves.

1 respuesta

Respuesta
1
Por experiencia te puedo decir que el predeterminar la relaciones no trae más que problemas. Es mucho mejor definir las relaciones cuando las necesitas, en las consultas, formularios... etc.
Si quieres insertar registros en las 2 tablas, efectivamente con Docmd. Runsql "Insert Into... creo que es la mejor forma.
En la página:
http://angelessebas.es/
En el apartado Formularios, supuesto: formulario para insertar registros tienen varios ejemplos.
Me cuentas.
Hola Angeles, gracias por la aclaración pero sigo teniendo problemas.
Tengo dos formularios
En el primer formulario relleno información para varios de los campos de la tabla1 (OFERTAS)
Luego en el segundo formulario tengo que mostrar el resto de los campos de OFERTAS para que el usuario pueda rellenerlos. Para ello me cree una variable global en la que almacene el numero de oferta introducida en formulario 1 y que es el identificador principal de la tabla1. Después metí en el evento cargar formulario Me. RecordSource = "SELECT [Tabla Ofertas].* ... para cambiar el campo de control del formulario.
Hasta ahí todo bien.
El problema viene que también quiero mostrar los datos de la tabla 2 (llamada NECESITA) en el formulario 2, ya que tiene que servir para consultar esos datos, insertarlos o realizar alguna modificación.
Al cargar formulario 2 he metido el siguiente código para cambiar el campo de control del formulario, eliminando el que tenia antes:
Me.RecordSource = "SELECT [Tabla Ofertas].* , [NECESITA].* FROM [Tabla Ofertas] INNER JOIN [NECESITA] ON [Tabla Ofertas].OFERTA=[NECESITA].ID_OFERTA WHERE OFERTA = " & Form!Texto58.Value
Donde Texto58 contiene el numero de oferta que estamos tratando.
Este código no da problemas, sin embargo el fallo viene más adelante.
El problema viene a que en la tabla2 NECESITA (ID_OFERTA, ID_COMPONENTE, ...) no esta relleno el campo ID_OFERTA. Había pensado en rellenarlo durante el evento de cargar formulario.
He probado con lo siguiente:
DoCmd.RunSql "Insert Into NECESITA (ID_OFERTA) Values (" & Form!Texto58.Value & ")"
Sin embargo al acceder al formulario 2 me sale una ventanita informándome que voy a anexar 1 fila y si deseo confirmar, le doy a Si y me sale otra ventanita para decirme que ha habido error, que access no ha podido hacerlo y que no ha podido agregar el registro a la tabla debido a infracciones entre claves.
Las relaciones son estas:
OFERTA(N_OFERTA, ...)
Necesita(id_oferta, id componente, ...)
Con una relación 1 a infinito ente N_OFERTA e ID_OFERTA.
¿Qué estoy haciendo mal? ¿He planteado correctamente el problema? Ando algo perdido como podrás leer.
Un saludo y gracias,
Sin ver la BD me es complicado ver dónde está el problema, si te parece me la mandas (en access 2003 y comprimida en zip o rar para que pese poco, te digo esto porque estoy de vacaciones y he contratado internet móvil, el mínimo, y por tanto tengo algún problema al bajar datos)
Me cuentas.
Hola Angeles,
Creo que una posible solución seria rellenar los campos de ID_OFERTA e ID_COMPONENTE al mismo tiempo.
Estoy probando con esto:
DoCmd.RunSQL "INSERT INTO NECESITA (ID_OFERTA, ID_PARAMETROS )SELECT (OFERTA FROM [Tabla Ofertas]) AND (COMPONENTE FROM [Tabla COMPONENTES]))WHERE OFERTA= " & Form!Texto58.Value
Sin embargo me da error de sintaxis, ¿es posible hacer un select de dos tablas distintas?
Un saludo y gracias
Pd: donde he puesto ID_PARAMETROS quería realmente escribir ID_COMPONENTE, lapsus mio. Sin embargo sigue habiendo error.
Para hacer un Select de 2 tablas tienes que tener un campo en común, que llamaremos por ejemplo IdClave y las tablas Tabla1 y tabla2. Para unirlas tienes que utilizar el INNER JOIN:
Select IdClave from tabla1 Inner Join Tabla2 ON tabla1.Idclave=tabla2.Idclave.
Me cuentas.
Hola Angeles, me explico mejor.
Mi objetivo es que al entrar al formulario2 me muestra parte de la tabla OFERTA y de la tabla NECESITA para una determinada Oferta (para realizar tanto consultas como para rellenar esos campos), sin embargo el problema viene a que la primera vez que accedo con una determinada oferta a dicho formulario2 la tabla NECESITA esta vacía, por lo tanto obtengo error.
De momento tengo al cargar formulario2 esta código, pero solo funciona si previamente he metido manualmente los campos ID_OFERTA e ID_COMPONENTE a la tabla NECESITA.
Form!Texto58.Value = var1
Me.RecordSource = "SELECT [Tabla Ofertas].* , [NECESITA].* FROM [Tabla Ofertas] INNER JOIN [NECESITA] ON [Tabla Ofertas].OFERTA=[NECESITA].ID_OFERTA WHERE OFERTA = " & Form!Texto58.Value
Siendo var1 una variable global donde he almacenado el identificador de la oferta con la que quiero trabajar, y el cual ha sido seleccionado previamente en un formulario anterior.
La tabla NECESITA tiene como campos principales ID_OFERTA e ID_COMPONENTE.
¿Qué solución me proponéis?
Un saludo y gracias,
Creo que lo primero que debes hacer es ver si la oferta existe en la tabla Necesita, si existe pones el código que tienes... si no lo que quieras...
If IsNull(DLookup("[id_oferta]","[necesita]","id_oferta=" & form!texto58.value & "")=false then
<el código que tienes>
else
msgbox "La oferta no existe en la tabla necesita"
end if
Me cuentas.
Hola Ángeles, gracias por el código, funciona. Ahora como podría añadir una fila a la tabla NECESITA teniendo en cuenta que ID_OFERTA e ID_COMPONENTE son sus claves principales. He intentado añadir ambos campos por separado pero me dice de anexar filas y da error por incompatibilidad entre claves. También he intentado añadirlos al mismo tiempo, sin embargo no lo he conseguido ... ¿alguna idea? El número de la Oferta esta recogida en la tabla Ofertas y en la variable global que he usado para pasar de formularios, mientras que el nombre de los componentes están almacenados en la tabla Componentes y son siempre los mismos para todas las ofertas.
Un saludo y muchas gracias.
No entiendo la pregunta, si id_oferta e id_componente están en la misma tabla, no deberías tener problema a la hora de insertarlos, siempre y cuando cumplan la ley de las claves únicas.
Pon un ejemplo a ver si me entero mejor.
Hola Angeles, en el formulario tengo varios cuadros de texto, con su respectiva etiqueta, en los cuales tengo que introducir la cantidad que quiero solicitar para cada componente para la oferta que seleccione antes de entrar a dicho formulario.
He intentado con esto:
Private Sub Texto201_AfterUpdate()
DoCmd.RunSQL "Insert Into NECESITA (ID_OFERTA, ID_COMPONENTE, CANTIDAD) Values (" & Form!Texto58.Value & ",'" & Form!Etiqueta202.Value & "'," & Form!Texto201.Value & ")"
End Sub
Es decir, que cada vez que introduzca una cantidad en un cuadro de texto, me introduzca una fila con la oferta en la que nos encontramos, el componente (el cual viene escrito en la etiqueta de la izquierda del cuadro de texto), y la cantidad introducida.
Sin embargo da el siguiente error: El objeto no admite esta propiedad o método.
He pensado como posible optativa introducir nada más entro al formulario todas las filas de la oferta que he seleccionado antes de entrar a dicho formulario con todos sus componentes (los cuales son iguales para todas las ofertas), es decir una cosa así:
Oferta Componente Cantidad
1 1
1 2
1 3
Dejando el campo cantidad vacío por el momento. Pienso que sería mejor solución que lo que te he escrito al principio, sin embargo esta opción también me da problemas y no se me ocurre como hacerlo.
¿Cómo podría abordar este problema?
Un saludo y muchas gracias,
Pd: No ha salido bien escrita la tabla, seria una cosa así
Oferta Componente Cantidad
1 ------------ 1
1 ------------ 2
1 ------------ 3
Las etiquetas no tienen valor, por eso te sale el error, las etiquetas, son eso, etiquetas informativas nada más. El valor lo dan los cuadros de texto, combinados...
Si el componente es siempre el mismo, en vez de
'" & Form!Etiqueta202.Value & "'
pon el nombre del componente;
'NombreDelComponente'
Hola Angeles, ahora si me deja insertar, lo malo es que cada vez que va a insertar me sale la dichosa ventanita avisándome de que voy a anexar 1 fila y si deseo aceptar o no. ¿Sabes cómo puedo evitarlo?
Private Sub Form_Load()
Form!Texto58.Value = var1
Form!Texto58.Locked = True
If IsNull(DLookup("[ID_OFERTA]", "[NECESITA]", "ID_OFERTA=" & Form!Texto58.Value & "") = False) Then
DoCmd.RunSQL "Insert Into NECESITA (ID_OFERTA, ID_COMPONENTE, CANTIDAD) Values (" & Form!Texto58.Value & ",'componente1','0')"
DoCmd.RunSQL "Insert Into NECESITA (ID_OFERTA, ID_COMPONENTE, CANTIDAD) Values (" & Form!Texto58.Value & ",'componente2','0')"
DoCmd.RunSQL "Insert Into NECESITA (ID_OFERTA, ID_COMPONENTE, CANTIDAD) Values (" & Form!Texto58.Value & ",'componente3','0')"
Ademas de esos tres campos, la tabla NECESITA tiene otros dos más, pero no creo que sea ese el motivo.
Un saludo y muchas gracias,
Lo puedes hacer de 2 formas:
1º.- Elimina los mensajes permanentemente: Vas a Herramientas ---> Opciones ---> Pestaña Modificar/Buscar ---> Confirmar (aquí chequeas o deschequeas lo que quieras confirmar o no)
2º.- Elimina los mensajes temporalmente: Método DoCmd. SetWarnings
Antes de ejecutar las consultas:
DoCmd.SetWarnings False (de esta forma eliminas los mensajes)
No olvides, cuando termines de ejecutar poner:
DoCmd. SetWarnings True (para que vuelva a dar los mensajes)
Muchísimas gracias Angeles, va perfecto. Voy a seguir trabajando en ello y si tengo alguna duda me paso por aquí. Te dejo la máxima puntuación posible.
Un saludo y muchas gracias.

Añade tu respuesta

Haz clic para o
El autor de la pregunta ya no la sigue por lo que es posible que no reciba tu respuesta.

Más respuestas relacionadas