2008-10-25 10 views
19

Poco a poco fui aprendiendo SQL en las últimas semanas. Recogí todo el álgebra relacional y los conceptos básicos de cómo funcionan las bases de datos relacionales. Lo que trato de hacer ahora es aprender cómo se implementa.Claves foráneas en MySQL?

Un obstáculo que he encontrado en esto, son las claves externas en MySQL. Parece que no puedo encontrar mucho más que el hecho de que existen en el esquema de almacenamiento InnoDB que tiene MySQL.

¿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 error 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; 

Respuesta

19

Suponiendo sus categorías y usuarios tabla ya existen y contienen Cid y UID, respectivamente, como claves primarias, 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 el nombre de columna es obligatorio en la cláusula references.

+0

Impresionante, gracias. – icco

3

This tiene algo de código que muestra cómo crear las claves externas por sí mismos, y en crear la tabla.

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

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; 
2

Estoy de acuerdo con Robert. Falta el nombre de la columna en la cláusula de referencias (y debería recibir el error 150). Voy a añadir que se puede comprobar cómo consiguieron las tablas creadas en realidad con:

SHOW CREATE TABLE posts; 
8

Editado: Robert y Vinko estado que tiene que declarar el nombre de la columna que se hace referencia en la restricción de clave externa. Esto es necesario en InnoDB, aunque en SQL estándar puede omitir el nombre de columna referenciado si tiene el mismo nombre en la tabla padre.

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

  • la instalación de MySQL no incluye el motor InnoDB
  • su archivo de configuración de MySQL no lo hace habilitar el motor InnoDB
  • no declara su mesa con el modificador ENGINE = InnoDB
  • la columna de clave externa no es exactamente el mismo tipo de datos que la columna de clave principal en la tabla referenciada

Desafortunadamente, MySQL no da ningún mensaje de que no ha podido crear la restricción de clave externa. Simplemente ignora la solicitud y crea la tabla sin la clave externa (si MUESTRA las publicaciones de CREATE TABLE, es posible que no vea ninguna declaración de clave externa). ¡Siempre pensé que esta es una mala característica de MySQL!

Consejo: el argumento entero para tipos de datos enteros (por ejemplo, BIGINT (20)) no es necesario. 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.

+0

¿Puede proporcionar una referencia a su reclamo con respecto a los nombres de las columnas en clave externa? De acuerdo con la sintaxis en (http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html) este no es un parámetro opcional y no funciona para mí a menos que especificarlo –

+0

Sí, tienes razón, ahora que lo pruebo con más cuidado, observo lo mismo. El SQL estándar debería permitir que el nombre de columna referenciado sea implícito si es el mismo en la tabla principal, pero InnoDB no lo admite, desafortunadamente. ¡Mea culpa! –

+0

He editado mi primer párrafo para ser más preciso. –

1

Las respuestas anteriores se refieren a la restricción de la 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 se usa la restricción o no.

Siempre que haga un equijoin, está equiparando una clave foránea con algo, normalmente 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 Students.StudentId.

+0

¿crees que podrías explicar qué está haciendo esto un poco más? ¿Es solo una unión? – icco

Cuestiones relacionadas