Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

[SOLUCIONADO] Problema con clave foranea

Estas en el tema de Problema con clave foranea en el foro de Mysql en Foros del Web. Buenas de nuevo: Estoy intentando crear una tabla llamada "GAS" con una foreign key que haga referencia a otra llamada "PROVEEDOR". El tema es que ...
  #1 (permalink)  
Antiguo 26/02/2016, 10:47
 
Fecha de Ingreso: noviembre-2015
Ubicación: Las Palmas (Canarias)
Mensajes: 14
Antigüedad: 8 años, 5 meses
Puntos: 0
Problema con clave foranea

Buenas de nuevo:

Estoy intentando crear una tabla llamada "GAS" con una foreign key que haga referencia a otra llamada "PROVEEDOR". El tema es que a pesar de poner los mismos tipos de datos no hay forma de crear la tabla con la foreign key.

Este es el script que he usado para la tabla PROVEEDOR:

Código MySQL:
Ver original
  1. create table proveedor (
  2. id_prove varchar(8) NOT NULL,
  3. nombre varchar(50),
  4. DNI varchar(10),
  5. cod_reparto int(5) NOT NULL,
  6. tipo_reparto varchar(50),
  7. fecha_entrega date,
  8. PRIMARY KEY (id_prove, cod_reparto)

Y este es el que pretendo usar para la tabla GAS:

Código MySQL:
Ver original
  1. cod_reparto int(5) NOT NULL,
  2. nom_prod varchar(50),
  3. fecha_entrega date,
  4. PRIMARY KEY (cod_reparto),
  5. FOREIGN KEY (cod_reparto) REFERENCES proveedor (cod_reparto) ON DELETE RESTRICT ON UPDATE CASCADE

Siempre me sale este error: 1215. Cannot add foreign key constraint.

¿Qué es lo que estoy haciendo mal?
  #2 (permalink)  
Antiguo 26/02/2016, 10:53
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 17 años, 8 meses
Puntos: 774
Respuesta: Problema con clave foranea

Lo que pasa es que tu primer tabla tiene 2 campos como llave primaria y tu quieres hacer la FK solo usando un campo, ahora en las tablas que mandas veo algunas cosas:
Código MySQL:
Ver original
  1. create table proveedor (
  2. id_prove varchar(8) NOT NULL,
  3. nombre varchar(50),
  4. DNI varchar(10),
  5. cod_reparto int(5) NOT NULL,
  6. tipo_reparto varchar(50),
  7. fecha_entrega date,
  8. PRIMARY KEY (id_prove, cod_reparto)

Aqui porque la llave primaria es una llave compuesta? si en la segunda tabla tienes que cod_reparto sea una llave primaria no veo la necesidad de tener la llave compuesta en la primer tabla

Crea tu primer tabla solo con una llave primaria:


Código MySQL:
Ver original
  1. create table proveedor (
  2. id_prove varchar(8) NOT NULL,
  3. nombre varchar(50),
  4. DNI varchar(10),
  5. cod_reparto int(5) NOT NULL,
  6. tipo_reparto varchar(50),
  7. fecha_entrega date,
  8. PRIMARY KEY (id_prove)
Y despues crea la segunda tabla con la referencia que tienes y veras que ahora si va a funcionar :)
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #3 (permalink)  
Antiguo 26/02/2016, 10:54
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Problema con clave foranea

Una FK es un campo o conjunto de campos que apunta a la PK de otra tabla. Cuando la PK referida tiene más de un campo, la FK debe tener la misma cantidad de campos, en el mismo orden y del mismo tipo de da,to, rango o collaltion.
Tu estás pretendiendo apuntar una FK a una PARTE de la PK, lo que es imposible.
Por otro lado, no se entiende para qué pones una PK de dos campos en la tabla Proveedor, si tienes un ID_PROVE, que se podría suponer con valores únicos.

Parece que tienes un diseño no muy bien acabado de tu base.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #4 (permalink)  
Antiguo 26/02/2016, 11:10
 
Fecha de Ingreso: noviembre-2015
Ubicación: Las Palmas (Canarias)
Mensajes: 14
Antigüedad: 8 años, 5 meses
Puntos: 0
Respuesta: Problema con clave foranea

Gracias a los dos.

Cierto es que tengo muchos fallos ya que esta es la primera Base de Datos que estoy creando por mi cuenta.

He hecho algunas, pero siempre siguiendo indicaciones del profesor... Y la verdad es que nunca tuve ese problema con las foreign keys porque, como he dicho, seguía indicaciones. He creado BBDD pero casi siempre por phpmyadmin o por el modo gráfico del Workbench... y recuerdo los comandos, pero no de forma específica.

Tengo que pulir mucho los diseños. Apunto este para la próxima.

Gracias de nuevo.
  #5 (permalink)  
Antiguo 26/02/2016, 11:17
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Problema con clave foranea

Antes que crear tablas tienes que definir las entidades del sistema.
Si un proveedor provee un sólo tipo de gas, pero ese tipo de gas puede ser provisto por mas de un proveedor tienes una relación 1:N entre ambos, y la FK de Gas va en Proveedor, y no al revés, pero a su vez esa FK NO ES parte de la PK. No confundir.
Si tu proveedor puede proveer más de un tipo de gas, la relación es N:M y requiere una tabla adicional. SI además puede cambiar a través del tiempo, la cosa se complica.

Empieza por definir las entidades del sistema, sus relaciones, y recién entonces podemos analizar como se deben implementar físicamente las mismas.

NO comiences con las paredes, sino con los cimientos.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #6 (permalink)  
Antiguo 26/02/2016, 12:06
 
Fecha de Ingreso: noviembre-2015
Ubicación: Las Palmas (Canarias)
Mensajes: 14
Antigüedad: 8 años, 5 meses
Puntos: 0
Respuesta: Problema con clave foranea

Cita:
Iniciado por Libras Ver Mensaje
Lo que pasa es que tu primer tabla tiene 2 campos como llave primaria y tu quieres hacer la FK solo usando un campo, ahora en las tablas que mandas veo algunas cosas:
Código MySQL:
Ver original
  1. create table proveedor (
  2. id_prove varchar(8) NOT NULL,
  3. nombre varchar(50),
  4. DNI varchar(10),
  5. cod_reparto int(5) NOT NULL,
  6. tipo_reparto varchar(50),
  7. fecha_entrega date,
  8. PRIMARY KEY (id_prove, cod_reparto)

Aqui porque la llave primaria es una llave compuesta? si en la segunda tabla tienes que cod_reparto sea una llave primaria no veo la necesidad de tener la llave compuesta en la primer tabla

Crea tu primer tabla solo con una llave primaria:


Código MySQL:
Ver original
  1. create table proveedor (
  2. id_prove varchar(8) NOT NULL,
  3. nombre varchar(50),
  4. DNI varchar(10),
  5. cod_reparto int(5) NOT NULL,
  6. tipo_reparto varchar(50),
  7. fecha_entrega date,
  8. PRIMARY KEY (id_prove)
Y despues crea la segunda tabla con la referencia que tienes y veras que ahora si va a funcionar :)
Cita:
Iniciado por gnzsoloyo Ver Mensaje
Antes que crear tablas tienes que definir las entidades del sistema.
Si un proveedor provee un sólo tipo de gas, pero ese tipo de gas puede ser provisto por mas de un proveedor tienes una relación 1:N entre ambos, y la FK de Gas va en Proveedor, y no al revés, pero a su vez esa FK NO ES parte de la PK. No confundir.
Si tu proveedor puede proveer más de un tipo de gas, la relación es N:M y requiere una tabla adicional. SI además puede cambiar a través del tiempo, la cosa se complica.

Empieza por definir las entidades del sistema, sus relaciones, y recién entonces podemos analizar como se deben implementar físicamente las mismas.

NO comiences con las paredes, sino con los cimientos.

Mi BBDD es un diseño de una Prisión. Además de las distintas relaciones entre el personal, los internos y demás, también existe una tabla con datos de los PROVEEDORES que proveen productos a la Prisión. Pero con eso que has dicho creo que me conviene más no crear la tabla GAS, ya que la forma en la que creé el diagrama E/R fue diseñando una jerarquía entre PROVEEDOR como supertipo y GAS, ALIMENTOS, MEDICINAS y ROPA como subtipo.

Esto lo hice en un principio porque pensé en crear una tabla específica para cada uno de los 4 tipos de repartos, pero si ya he creado PROVEEDOR con datos como "cod_reparto", "tipo_reparto" y "fecha_entrega" no veo necesario que exista otra tabla para lo mismo. Eso me parece que crea mucha redundancia.

Respecto al diagrama E/R lo llevo más o menos. Las cardinalidades que he puesto entre la tabla PROVEEDOR y PRISION es 1:N, porque en la Prisión proveen 1:N proveedores, mientras que un proveedor solo provee a 0:1 prisión.
Esto es porque esta Prisión, al ser ficticia, va a ser "construida" en una isla donde no existe ninguna...
Creo que lo he planteado bien, para lo que intento hacer. Pero aún soy muy novata en esto.
  #7 (permalink)  
Antiguo 26/02/2016, 18:22
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Problema con clave foranea

Cita:
ya que la forma en la que creé el diagrama E/R fue diseñando una jerarquía entre PROVEEDOR como supertipo y GAS, ALIMENTOS, MEDICINAS y ROPA como subtipo.
Gas, Alimentos y Ropa no pueden ser jamás "subtipos" de Proveedor. Eso no tiene sentido.
Por lo pronto, no existe la clasificación de "subtipos" en BBDD, al menos como concepto de clase. Son herencias de entidades jerárquicas, pero en una estructura de herencia, las entidades hijas deben forzosamente ser una especialización de la entidad padre. SIEMPRE.
Y no es posible establecer desde Proveedor una especialización que te de como resultado Gas, Ropa o Alimentos. Es imposible. Simplemente no es racional.
En todo caso los tres componentes mencionados son hijos de otra entidad, llámale "provisión", "abastos", o como quieras. Pero es esa otra entidad la que se relaciona con Proveedor.

¿Se entiende?

Con una entidad "Abastos", por ejemplo, sí puedes establecer una especialización de ese tipo.

Luego de eso, obtienes la relacion entre proveedor y compras. Esa relación es N:M porque un mismo tipo de abasto o producto puede ser provisto por N proveedores, y cada proveedor puede proveer N tipos de productos o subproductos.
De todos modos, el modelo queda incompleto, porque si existen proveedores, hay que consiuderar que:
1) Cada proveedor debe recibir una orden de pedido.
2) Cada proveedor entrega facturas, remitos y emite recibos por los pagos.
3) La Prisión debe tener asentado en algula parte qué facturas de que proveedor debe abonar, y cuando.
4) Los remitos de los proveedores deben ingresar como compras realizadas en alguna parte.
5) Cada ingreso de provisiones debe ser asentada en fecha de ingreso y cantidad.
6) Los tipos de producto pueden tener fechas de vencimiento, por lo que hay que considerar qu eal ser usadas la lógica de stock puede ser FIFO o LIFO. De acuerdo a eso se deben resolver procesos y datos.

Todo esto y mucho mas debe ser relevado, o planteado como supuestos asumidos antes de diseñar la solución. Y deben quedar escritos.

Otros detalles:
La relación entre Proveedor y Prision sí puede ser 1:1 mirada desde el proveedor, pero es 1:N desde la optica de la Prisión, por lo que la tabla Proveedor contiene la FK de Prisión.
El hecho que haya una sola Prisión en la isla es irrelevante. De todos modos a nivel de diseño se exige que exista la entidad Prisión, aunque tenga un solo registro.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #8 (permalink)  
Antiguo 27/02/2016, 07:10
 
Fecha de Ingreso: noviembre-2015
Ubicación: Las Palmas (Canarias)
Mensajes: 14
Antigüedad: 8 años, 5 meses
Puntos: 0
Respuesta: Problema con clave foranea

Cita:
Iniciado por gnzsoloyo Ver Mensaje
Gas, Alimentos y Ropa no pueden ser jamás "subtipos" de Proveedor. Eso no tiene sentido.
Por lo pronto, no existe la clasificación de "subtipos" en BBDD, al menos como concepto de clase. Son herencias de entidades jerárquicas, pero en una estructura de herencia, las entidades hijas deben forzosamente ser una especialización de la entidad padre. SIEMPRE.
Y no es posible establecer desde Proveedor una especialización que te de como resultado Gas, Ropa o Alimentos. Es imposible. Simplemente no es racional.
En todo caso los tres componentes mencionados son hijos de otra entidad, llámale "provisión", "abastos", o como quieras. Pero es esa otra entidad la que se relaciona con Proveedor.

¿Se entiende?

Con una entidad "Abastos", por ejemplo, sí puedes establecer una especialización de ese tipo.

Luego de eso, obtienes la relacion entre proveedor y compras. Esa relación es N:M porque un mismo tipo de abasto o producto puede ser provisto por N proveedores, y cada proveedor puede proveer N tipos de productos o subproductos.
De todos modos, el modelo queda incompleto, porque si existen proveedores, hay que consiuderar que:
1) Cada proveedor debe recibir una orden de pedido.
2) Cada proveedor entrega facturas, remitos y emite recibos por los pagos.
3) La Prisión debe tener asentado en algula parte qué facturas de que proveedor debe abonar, y cuando.
4) Los remitos de los proveedores deben ingresar como compras realizadas en alguna parte.
5) Cada ingreso de provisiones debe ser asentada en fecha de ingreso y cantidad.
6) Los tipos de producto pueden tener fechas de vencimiento, por lo que hay que considerar qu eal ser usadas la lógica de stock puede ser FIFO o LIFO. De acuerdo a eso se deben resolver procesos y datos.

Todo esto y mucho mas debe ser relevado, o planteado como supuestos asumidos antes de diseñar la solución. Y deben quedar escritos.

Otros detalles:
La relación entre Proveedor y Prision sí puede ser 1:1 mirada desde el proveedor, pero es 1:N desde la optica de la Prisión, por lo que la tabla Proveedor contiene la FK de Prisión.
El hecho que haya una sola Prisión en la isla es irrelevante. De todos modos a nivel de diseño se exige que exista la entidad Prisión, aunque tenga un solo registro.


Si algo me quedaba claro es que una tabla con los datos de la PRISIÓN debía existir, aunque solo exista un registro, si no deja de tener sentido toda la BD.

Por lo pronto he añadido datos a las tablas conforme a lo que has dicho, los datos de albarán, las fechas de vencimiento, recibos, incluyendo la FK de la PRISIÓN en PROVEEDORES...
Si no me equivoco son los del departamento de contabilidad los que emiten los recibos, mientras que los datos de albarán pueden incluirse dentro de una tabla tipo ALMACENAJE o cualquier otro nombre más conveniente. Es decir, lo recomendable es crear tablas para recibir los datos de los envíos y ligarlos con FK a la tabla PROVEEDORES o ABASTOS.

También he normalizado algunas tablas que tenían exceso de columnas que, tal y como se explica en la normalización, es necesario crear más tablas con FK ligadas a ellas para no saturar de datos una sola tabla.

Pero voy a aprovechar que tengo contactos en una Prisión por mi zona y a preguntarle varias cosas, o quizás me sea más conveniente ir y ver cómo se organiza todo... Si no, al final voy a terminar creando una BD incompleta.

Gracias por la información.
  #9 (permalink)  
Antiguo 27/02/2016, 09:29
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Problema con clave foranea

Cita:
También he normalizado algunas tablas que tenían exceso de columnas que, tal y como se explica en la normalización, es necesario crear más tablas con FK ligadas a ellas para no saturar de datos una sola tabla.
Bueno, en realidad no se normaliza por "exceso" de datos, sino que se debe normalizar cuando hay datos que se repiten en diferentes tablas (de alli que no deba ir el nombre de un articulo en la tabla de detalle de factura, por ejemplo).
Hay que ver exactamente que se normaliza y por qué.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Etiquetas: clave, fecha, tabla
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 23:29.