Comunidad de diseño web y desarrollo en internet online

LLaves foraneas

Citar            
MensajeEscrito el 27 Feb 2015 02:23 am
Hola este es mi primer tema, lamento que sea para pedir ayuda en lugar de ayudarlos :( .....espero que me puedan ayudar he andado buscando informacion pero nada, sin mas les comento:


tengo dos tablas: usuarios y materia, quiero crear una tabla llamada alumnos la cual tenga llaves foraneas hacia usuarios y a la tabla materia, ahora he realizado las llaves foraneas con el tipo de dato "Int" a otro "Int" y si me ha corrido, pero al hacerlo de "varchar " a "varchar" no me permite, me sale el siguiente error:
ERROR 1215 (HY000): Impossible d'ajouter des contraintes d'index externe
ese error me sale al intentar crear la tabla alumno.
Ahora no se a que se deba, he leido que si se pueden hacer llaves foraneas con varchar, y ese es mi caso, tengo la misma longitud y el mismo tipo de dato, pero no funciona, les dejo el código, espero que me puedan ayudar, se los agradeceria mucho, al igual acepto sugerencias...saludos desde mexico ^^

Código MySQL :

create table usuarios(
id_usuario int auto_increment,
login varchar(20) not null,
clave varchar(16) not null,
nivel varchar(20) not null,
primary key(id_usuario,login,clave)
) engine innodb;

create table materia(
id_materia int auto_increment,
nombre varchar(30) not null,
duracion date,
primary key(id_materia,nombre)
) engine innodb;

create table alumno(
id_alumno varchar(11) not null,
nombre varchar(20) not null,
apellidos varchar(40) not null,
direccion varchar(30) not null,
telefono int,
email varchar(40),
login_alumno varchar(20) not null,
clave_alumno varchar(16) not null,
materia_alumno varchar(30) not null,
foreign key(login_alumno) references usuarios(login) on update cascade on delete cascade,
foreign key(clave_alumno) references usuarios(clave) on update cascade on delete cascade,
foreign key(materia_alumno) references materia(nombre) on update cascade on delete cascade,
primary key (id_alumno)
) engine innodb;

Por Tekn

5 de clabLevel



Genero:Masculino  

chrome
Citar            
MensajeEscrito el 27 Feb 2015 02:57 pm
Pues como yo lo veo, no necesitas tener los campos "login_alumno" y "clave_alumno" en la tabla alumno, solamente un campo que apunte a "id_usuario" de la tabla usuarios y otro campo que apunte a id_materia en la tabla "materia".

El error lo causa el hecho de que en las tablas "usuarios" y "materia" todas las claves son de tipo "PRIMARY" cuando solamente el id debe serlo, el resto de los campos que quieres que sean indice deben ser de tipo "INDEX".

Aunque más general veo problemas con el diseño general de todo esto. Por ejemplo, la tabla "alumno" parece ser una continuación de la tabla "usuarios" así que no necesitas esa tabla, podrías poner todos los campos de "alumnos" en la misma tabla de "usuarios". Excepto el campo "materia_alumno". Ese campo sugiere que es un grupo repetitivo. O sea, hay una relación de uno a muchos entre alumnos y materias (un alumno->muchas materias).

Para mi que lo que has querido hacer es lo siguiente:

Código MySQL :

CREATE TABLE IF NOT EXISTS `usuarios` (
`id_usuario` int(11) NOT NULL,
  `login` varchar(20) DEFAULT NULL,
  `clave` varchar(16) DEFAULT NULL,
  `nivel` varchar(20) latin1 DEFAULT NULL,
  `nombre` varchar(20) DEFAULT NULL,
  `apellidos` varchar(40) DEFAULT NULL,
  `direccion` varchar(30) DEFAULT NULL,
  `telefono` varchar(20) DEFAULT NULL,
  `email` varchar(40) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Indice de la tabla `usuarios`
ALTER TABLE `usuarios`
 ADD PRIMARY KEY (`id_usuario`), ADD KEY `login` (`login`);

-- AUTO_INCREMENT de la tabla `usuarios`
ALTER TABLE `usuarios`
MODIFY `id_usuario` int(11) NOT NULL AUTO_INCREMENT;

- -----------------------------------------
CREATE TABLE IF NOT EXISTS `materias` (
`id_materia` int(11) NOT NULL,
  `nombre` varchar(20) DEFAULT NULL,
  `duracion` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Indices de la tabla `materias`
ALTER TABLE `materias`
 ADD PRIMARY KEY (`id_materia`);

-- AUTO_INCREMENT de la tabla `materias`
ALTER TABLE `materias`
MODIFY `id_materia` int(11) NOT NULL AUTO_INCREMENT;

-- ---------------------------------

CREATE TABLE IF NOT EXISTS `materias_por_alumno` (
  `id_usuario` int(11) NOT NULL,
  `id_materia` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Indices de la tabla `materias_por_alumno`
ALTER TABLE `materias_por_alumno`
 ADD KEY `id_usuario` (`id_usuario`), ADD KEY `id_materia` (`id_materia`);

-- Filtros para la tabla `materias_por_alumno`
ALTER TABLE `materias_por_alumno`
ALTER TABLE `materias_por_alumno`
ADD CONSTRAINT `materias_por_alumno_ibfk_1` FOREIGN KEY (`id_usuario`) REFERENCES `usuarios` (`id_usuario`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `materias_por_alumno_ibfk_2` FOREIGN KEY (`id_materia`) REFERENCES `materias` (`id_materia`) ON DELETE CASCADE ON UPDATE CASCADE;


Los CONSTRAIT en la tabla "materias_por_alumno" hacen que cuando se borre una materia, se borren las relaciones entre esa materia y los alumnos (lo mismo si se borra un usuario).

Acá está el volcado de las tablas para que pruebes:

Código MySQL :

INSERT INTO `materias` (`id_materia`, `nombre`, `duracion`) VALUES
(1, 'eurgheiurghieruhg', '2015-09-30'),
(2, 'iuthiruthgiuhg', '2015-10-25'),
(3, 'eirughieur dbveuyrg', '2015-11-01');

INSERT INTO `materias_por_alumno` (`id_usuario`, `id_materia`) VALUES
(1, 1),
(1, 2),
(2, 2),
(2, 3);

INSERT INTO `usuarios` (`id_usuario`, `login`, `clave`, `nivel`, `nombre`, `apellidos`, `direccion`, `telefono`, `email`) VALUES
(1, 'lkjfwioowie', 'iquiquhiuq', 'iwuefiwueh', 'Juan', 'Perez', 'woiefwie  owiefow efo987', '298329834782', '[email protected]'),
(2, 'eiurhieurhgiuer', 'wuyegfuwyegf', 'sjkeliuweiuwe', 'Maria', 'Lopez', 'wiueiuefiwue wiuehfiuwhefu', '82762763', '[email protected]');


Puedes hacer lo siguiente. Agrega una materia nueva. Asígnale esa nueva materia al alumino 2 (id_usuario=2) y luego borra la materia de la tabla materias. Verás que la relación desaparece de la tabla "materias_por_usuario" también.

Para saber cuáles materias tiene un alumno basta con leer la tabla "materias_por_alumno" y relacionarla con las otras tablas:

Código MySQL :

SELECT * FROM `materias_por_alumno`, `usuarios`, `materias`
WHERE `materias_por_alumno`.`id_usuario` = 1
AND `materias_por_alumno`.`id_materia` = `materias`.`id_materia`
AND `materias_por_alumno`.`id_usuario` = `usuarios`.`id_usuario`

Por DriverOp

Claber

2510 de clabLevel



 

opera
Citar            
MensajeEscrito el 27 Feb 2015 04:28 pm
Hola driverop, primero muchas gracias por atender este tema :D , de verdad se agradece, mira te explico:
tengo una base de datos, en la cual administrare un control escolar, mis tablas son:
*usuarios
*alumnos
*docentes
*materia
*cargaacademica

los usuarios son para acceder al sistema por eso solo requeria lo que era el
id_usuario= auto_increment para llevar un conteo de usuarios
login= sobrenombre o nick del usuario.
clave= clave para acceder al sistema.
nivel= este puede ser ('administrador','docente' y 'alumno')
ahora cree una clave primaria compuesta( la cual contiene el id_usuario,login y clave) esto porque ningun alumno y docente pueden tener los mismos campos de (id_usuario,login y clave).

En la tabla materia:
id_materia= identificador de la materia auto_increment porque se lleva un control ascendente de la materia.
nombre= nombre de la materia.
duracion de tipo date: los cursos duran semanas(4 como ejemplo).
y tambien cree una clave primaria compuesta(id_materia y nombre) porque ninguna materia puede tener el mismo identificador y nombre.

Tabla alumno:(aqui esta la informacion referente al alumno)
id_alumno= matricula del alumno.
nombre
apellidos
direccion
telefono(yo utilize int porque es local, no hay ladas internacionales, yo creo que utilizaste el varchar por eso de las ladas internacionales o codigos ejemplo: +5212736665544)
email

ahora las relaciones entre tablas que intente implementar:

Código MySQL :

login_alu varchar(20) not null,
clave_alu varchar(16) not null,
materia_alu varchar(30) not null,
foreign key(login_alu) references usuarios(login) on update cascade on delete cascade,
foreign key(clave_alu) references usuarios(clave) on update cascade on delete cascade,
foreign key(materia_alu) references materia(nombre) on update cascade on delete cascade

esto para que solo un alumno tenga un solo login, una sola clave y una sola materia asignada.
Tu codigo lo probe y corrio la mayoria de codigo, bueno hasta la seccion filtro pata tabla 'materias__por_alumno''


-- Filtros para la tabla `materias_por_alumno`

Código MySQL :

ALTER TABLE `materias_por_alumno`
ALTER TABLE `materias_por_alumno`
ADD CONSTRAINT `materias_por_alumno_ibfk_1` FOREIGN KEY (`id_usuario`) REFERENCES `usuarios` (`id_usuario`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `materias_por_alumno_ibfk_2` FOREIGN KEY (`id_materia`) REFERENCES `materias` (`id_materia`) ON DELETE CASCADE ON UPDATE CASCADE;


Los CONSTRAIT en la tabla "materias_por_alumno" hacen que cuando se borre una materia, se borren las relaciones entre esa materia y los alumnos (lo mismo si se borra un usuario).


y me salio este error:
ERROR 1064 (42000): Erreur de syntaxe près de 'TABLE `materias_por_alumno`
ADD CONSTRAINT `materias_por_alumno_ibfk_1` FOREIGN ' à la ligne 2

Una vez mas te agradezco que me estes ayudando, saludos y espero respondas pronto. ^^

Por Tekn

5 de clabLevel



Genero:Masculino  

chrome
Citar            
MensajeEscrito el 27 Feb 2015 06:46 pm

Tekn escribió:

los usuarios son para acceder al sistema por eso solo requeria lo que era el
id_usuario= auto_increment para llevar un conteo de usuarios
login= sobrenombre o nick del usuario.
clave= clave para acceder al sistema.
nivel= este puede ser ('administrador','docente' y 'alumno')
ahora cree una clave primaria compuesta( la cual contiene el id_usuario,login y clave) esto porque ningun alumno y docente pueden tener los mismos campos de (id_usuario,login y clave).

En ese caso tampoco necesitas que el indice PRIMARY sea compuesto. Basta con que pongas como índice de tipo UNIQUE el campo login (el campo clave sí se puede repetir, porque dos usuarios distintos pueden tener la misma clave.

Tekn escribió:


En la tabla materia:
id_materia= identificador de la materia auto_increment porque se lleva un control ascendente de la materia.
nombre= nombre de la materia.
duracion de tipo date: los cursos duran semanas(4 como ejemplo).
y tambien cree una clave primaria compuesta(id_materia y nombre) porque ninguna materia puede tener el mismo identificador y nombre.

Mismo comentario que el anterior. Basta con poner el campo "nombre" con índice UNIQUE.

Tekn escribió:


Tabla alumno:(aqui esta la informacion referente al alumno)
id_alumno= matricula del alumno.
nombre
apellidos
direccion
telefono(yo utilize int porque es local, no hay ladas internacionales, yo creo que utilizaste el varchar por eso de las ladas internacionales o codigos ejemplo: +5212736665544)
email

No solo por eso. Hay teléfonos de centrales donde además de número, hay que marcar una extensión con numeral Ej: 0111566677#45 (número 0111566677, extensión 45).

Tekn escribió:


ahora las relaciones entre tablas que intente implementar:
y me salio este error:
ERROR 1064 (42000): Erreur de syntaxe près de 'TABLE `materias_por_alumno`
ADD CONSTRAINT `materias_por_alumno_ibfk_1` FOREIGN ' à la ligne 2

Una vez mas te agradezco que me estes ayudando, saludos y espero respondas pronto. ^^

Se me debió romper la copia. "ALTER TABLE `materias_por_alumno`" debe aparecer una sola vez.

Por DriverOp

Claber

2510 de clabLevel



 

opera
Citar            
MensajeEscrito el 27 Feb 2015 07:04 pm
Gracias...lo que entendi es que no necesariamente es una clave compuesta, realize esto, asigne la llave primaria a id_usuario y UNIQUE al campo login, es lo que me sugeriste o entendi mal...gracias de antemano

Código MySQL :

create table usuarios(
id_usuario int auto_increment not null primary key,
login varchar(20) not null,
clave varchar(16) not null,
nivel varchar(20) not null,
unique (login)
) engine = innodb;

Por Tekn

5 de clabLevel



Genero:Masculino  

chrome
Citar            
MensajeEscrito el 27 Feb 2015 07:11 pm
Lo has entendido bien ;)

Por DriverOp

Claber

2510 de clabLevel



 

opera
Citar            
MensajeEscrito el 27 Feb 2015 07:35 pm
Gracias...es la misma situacion para materias me lo habias mencionado arriba, la tabla alumnos quedaria asi:

Código MySQL :

create table alumno(
id_alumno varchar(11) primary key ,
nombre varchar(20) not null,
apellidos varchar(40) not null,
direccion varchar(30) not null,
telefono int,
email varchar(40),
login_alu varchar(20) not null,
clave_alu varchar(16) not null,
materia_alu varchar(30) not null,
foreign key(login_alu) references usuarios(login) on update cascade on delete cascade,
foreign key(materia_alu) references materia(nombre) on update cascade on delete cascade
) engine = innodb;


o he entendido mal...

Por Tekn

5 de clabLevel



Genero:Masculino  

chrome
Citar            
MensajeEscrito el 27 Feb 2015 08:35 pm
ya lo implemente y probe insertando registros, tanto en la tabla usuarios, materias y en la de alumnos, tambien implemente la tabla docente y tambien ha corrido bien, ahora te molesto nuevamente con la tabla carga, como podria realizarla es que me piden que tenga:
id_carga auto_increment
alu---nombre del alumno referenciado al nombre de algun alumno registrado
doc--nombre de docente referenciado al nombre de un docente registrado
materia-nombre de materia registrada
fecha_inicio--cuando inicio el curso
calificacion int---para asignar un calificacion una vez terminado el curso...


muchas gracias de antemano

Por Tekn

5 de clabLevel



Genero:Masculino  

chrome
Citar            
MensajeEscrito el 27 Feb 2015 11:09 pm
Driverop muchas gracias, ya pude implementarla, solo es cosa de ejecutar consultas:
ejemplo
select *
from materia t, docentes p
where t.nombre = p.id_nombre

te agradezco que me hayas ayudado, saludos!!!

Por Tekn

5 de clabLevel



Genero:Masculino  

chrome
Citar            
MensajeEscrito el 02 Mar 2015 12:31 pm
Un placer haber sido útil :)

Por DriverOp

Claber

2510 de clabLevel



 

opera

 

Cristalab BabyBlue v4 + V4 © 2011 Cristalab
Powered by ClabEngines v4, HTML5, love and ponies.