Pregunta

He estado aprendiendo lentamente SQL las últimas semanas. He recogido todo el álgebra relacional y los conceptos básicos de cómo funcionan las bases de datos relacionales. Lo que intento hacer ahora es aprender cómo se implementa.

Un obstáculo que he encontrado en esto, son las claves foráneas en MySQL. Parece que no puedo encontrar mucho sobre el otro que existe en el InnoDB esquema de almacenamiento que MySQL tiene.

¿Cuál es un ejemplo simple de claves externas implementadas en MySQL?

Aquí hay parte de un esquema que escribí que no parece funcionar si prefieres señalar mi falla antes que mostrarme un ejemplo de trabajo.

CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY  (`pID`),
Foreign Key(`cID`) references categories,
Foreign Key(`uID`) references users
) ENGINE=InnoDB;
¿Fue útil?

Solución

Suponiendo que sus categorías y tabla de usuarios ya existan y contengan cID y uID respectivamente como claves principales, esto debería funcionar:

CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY  (`pID`),
Foreign Key(`cID`) references categories(`cID`),
Foreign Key(`uID`) references users(`uID`)
) ENGINE=InnoDB;

El nombre de la columna se requiere en la cláusula referencias .

Otros consejos

Editado: Robert y Vinko afirman que debe declarar el nombre de la columna referenciada en la restricción de clave externa. Esto es necesario en InnoDB, aunque en SQL estándar se le permite omitir el nombre de columna al que se hace referencia si es el mismo nombre en la tabla principal.

Una idiosincrasia que he encontrado en MySQL es que la declaración de clave externa fallará en silencio en varias circunstancias:

  • Su instalación de MySQL no incluye el motor innodb
  • Su archivo de configuración MySQL no habilita el motor innodb
  • No declara su tabla con el modificador de tabla ENGINE = InnoDB
  • La columna de clave externa no es exactamente el mismo tipo de datos que la columna de clave primaria en la tabla referenciada

Desafortunadamente, MySQL no da ningún mensaje de que no haya podido crear la restricción de clave externa. Simplemente ignora la solicitud y crea la tabla sin la clave foránea (si MOSTRAS publicaciones de TABLE CREATE, es posible que no veas una declaración de clave foránea). ¡Siempre he pensado que esta es una mala característica de MySQL!

Sugerencia: no es necesario el argumento entero para los tipos de datos enteros (por ejemplo, BIGINT (20)). No tiene nada que ver con el tamaño de almacenamiento o el rango de la columna. BIGINT siempre tiene el mismo tamaño, independientemente del argumento que le des. El número se refiere a cuántos dígitos MySQL rellenará la columna si usa el modificador de columna ZEROFILL.

Esto tiene algunos código que muestra cómo crear claves foráneas por sí mismos y en CREATE TABLE.

Aquí está uno de los ejemplos más simples de eso:

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (
    id INT, 
    parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id) REFERENCES parent(id)
    ON DELETE CASCADE
) ENGINE=INNODB;

Estoy de acuerdo con Robert. Le falta el nombre de la columna en la cláusula de referencias (y debería recibir el error 150). Agregaré que puede verificar cómo se crearon las tablas en realidad con:

SHOW CREATE TABLE posts;

Las respuestas anteriores tratan con la restricción de clave externa. Si bien la restricción de clave externa es definitivamente útil para mantener la integridad referencial, el concepto de "clave externa" en sí mismo es fundamental para el modelo relacional de datos, independientemente de si usa la restricción o no.

Siempre que haces un equijoin , estás igualando una clave foránea para algo, generalmente la clave a la que hace referencia. Ejemplo:

select *
from 
   Students
inner join
   StudentCourses
on Students.StudentId = StudentCourses.StudentId

StudentCourses.StudentId es una clave externa que hace referencia a Students.StudentId.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top