¿Cómo veo todas las claves externas de una tabla o columna?

567

En MySQL, ¿cómo obtengo una lista de todas las restricciones de clave externa que apuntan a una tabla en particular? una columna en particular? Esto es lo mismo que esta pregunta de Oracle , pero para MySQL.

Christian Oudard
fuente

Respuestas:

764

Para una mesa:

SELECT 
  TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM
  INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
  REFERENCED_TABLE_SCHEMA = '<database>' AND
  REFERENCED_TABLE_NAME = '<table>';

Para una columna:

SELECT 
  TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM
  INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
  REFERENCED_TABLE_SCHEMA = '<database>' AND
  REFERENCED_TABLE_NAME = '<table>' AND
  REFERENCED_COLUMN_NAME = '<column>';

Básicamente, cambiamos REFERENCED_TABLE_NAME con REFERENCED_COLUMN_NAME en la cláusula where.

Vinko Vrsalovic
fuente
26
esto siempre me da un conjunto vacío, mientras que la consulta propuesta por Node a continuación funciona bien
Agudo
77
@Acute: ¿Estás seguro de que estás preguntando por la tabla correcta? Si la consulta de Node funciona, es probable que esté preguntando sobre la otra dirección (es decir, las teclas FROM mytable, no las teclas TO mytable). Esto espera que haya escrito '<table>' con el nombre de la tabla y sin '<' y '>' ?
Vinko Vrsalovic
3
Parece que no entendí su consulta, porque estaba buscando claves que hicieran referencia a <table> :) (sí, escribí el nombre de la tabla en lugar de "<table>" XD)
Agudo
44
A menos que esté seguro de que el nombre de su tabla es único, probablemente también desee restringir su consulta a una base de datos en particular. Cambie la cláusula where a esto:where REFERENCED_TABLE_SCHEMA = 'mydatabase' and REFERENCED_TABLE_NAME = 'mytable'
user12345
Esto no funcionará en el caso de usuarios no root, aunque el usuario tenga todos los permisos para la base de datos
Deepak Ram
275

EDITAR: Como se señaló en los comentarios, esta no es la respuesta correcta a la pregunta de los OP, pero es útil conocer este comando. Esta pregunta apareció en Google para lo que estaba buscando, y pensé que dejaría esta respuesta para que los demás la encuentren.

SHOW CREATE TABLE `<yourtable>`;

Encontré esta respuesta aquí: MySQL: mostrar restricciones en el comando de tablas

Necesitaba de esta manera porque quería ver cómo funcionaba el FK, en lugar de solo ver si existía o no.

CenterOrbit
fuente
37
Esto muestra todas las restricciones <yourtable>, no todas las restricciones que apuntan <yourtable>.
Barmar
18
Como dice @Barmar, esto está completamente mal; se mostrará las claves externas que pertenecen a la tabla especificada, pero no mostrará las claves externas apuntando A la mesa, que es lo que la pregunta se refiere. No tengo idea de cómo esto obtuvo 50 votos a favor; Supongo que las personas terminaron aquí cuando realmente estaban buscando la respuesta a la pregunta opuesta, encontraron su respuesta aquí de todos modos, y no se molestaron en leer la pregunta original (o incluso su título) antes de votar.
Mark Amery
2
@ MarkAmery: este es el primer resultado display foreign keys mysqlen google, puede ser por eso;)
Jigar
1
thisi en realidad muestra todas las restricciones que existen, phpmyadmin solo le mostrará la que apunta a su tabla. parece lo suficientemente bueno como para evitar duplicados con una herramienta ORM
william.eyidi
3
Esto es lo que estaba buscando, así que gracias por publicarlo a pesar de que no respondió la pregunta de OP. ¡Nunca está de más saber cómo mirar en ambas direcciones en una relación!
Charles Wood
75

Si utiliza InnoDB y FK definidos, puede consultar la base de datos information_schema, por ejemplo:

SELECT * FROM information_schema.TABLE_CONSTRAINTS 
WHERE information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'FOREIGN KEY' 
AND information_schema.TABLE_CONSTRAINTS.TABLE_SCHEMA = 'myschema'
AND information_schema.TABLE_CONSTRAINTS.TABLE_NAME = 'mytable';
Nodo
fuente
15
en realidad, eso señala la dirección equivocada. esa consulta muestra todas las claves foráneas apuntando desde 'mytable', no todas las claves foráneas apuntando hacia 'mytable'.
Christian Oudard
1
Este funciona mejor en mi caso. Necesito eliminar cada restricción de clave externa (y solo aquellas) de una tabla para poder cambiar el motor InnoDB MyISAM o NDB.
Kohányi Róbert
Puede obtener claves foráneas en ambas direcciones desde la tabla REFERENTIAL_CONSTRAINTS. He agregado otra respuesta con la consulta.
ChrisV
45

Publicar en una respuesta anterior para agregar información útil.

Tuve un problema similar, pero también quería ver CONSTRAINT_TYPE junto con la tabla REFERENCIADA y los nombres de columna. Entonces,

  1. Para ver todos los FK en su tabla:

    USE '<yourschema>';
    
    SELECT i.TABLE_NAME, i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME 
    FROM information_schema.TABLE_CONSTRAINTS i 
    LEFT JOIN information_schema.KEY_COLUMN_USAGE k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME 
    WHERE i.CONSTRAINT_TYPE = 'FOREIGN KEY' 
    AND i.TABLE_SCHEMA = DATABASE()
    AND i.TABLE_NAME = '<yourtable>';
    
  2. Para ver todas las tablas y FK en su esquema:

    USE '<yourschema>';
    
    SELECT i.TABLE_NAME, i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME 
    FROM information_schema.TABLE_CONSTRAINTS i 
    LEFT JOIN information_schema.KEY_COLUMN_USAGE k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME 
    WHERE i.CONSTRAINT_TYPE = 'FOREIGN KEY' 
    AND i.TABLE_SCHEMA = DATABASE();
    
  3. Para ver todos los FK en su base de datos:

    SELECT i.TABLE_SCHEMA, i.TABLE_NAME, i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME 
    FROM information_schema.TABLE_CONSTRAINTS i 
    LEFT JOIN information_schema.KEY_COLUMN_USAGE k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME 
    WHERE i.CONSTRAINT_TYPE = 'FOREIGN KEY';

¡Recuerda!

Esto está utilizando el motor de almacenamiento InnoDB. Si parece que no puede mostrar ninguna clave foránea después de agregarla, probablemente sea porque sus tablas están usando MyISAM.

Verificar:

SELECT * TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = '<yourschema>';

Para solucionarlo, use esto:

ALTER TABLE `<yourtable>` ENGINE=InnoDB;
Andy
fuente
8
Esas consultas se ejecutan mucho más rápido (de 2 segundos a 0.0015 segundos) si especifica k.TABLE_SCHEMA = DATABASE () y k.TABLE_NAME = '<table>' en la cláusula WHERE, como se documenta aquí dev.mysql.com/doc/refman /5.5/en/…
guigouz
2
gran respuesta. ¿Tienes alguna solución para MyISAM?
Beau Bouchard
2
MyISAM no admite claves foráneas, desafortunadamente. dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
Andy
24

Como alternativa a la respuesta de Node, si usa InnoDB y define FK, puede consultar la base de datos information_schema, por ejemplo:

SELECT CONSTRAINT_NAME, TABLE_NAME, REFERENCED_TABLE_NAME
FROM information_schema.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = '<schema>'
AND TABLE_NAME = '<table>'

para claves foráneas de <table>, o

SELECT CONSTRAINT_NAME, TABLE_NAME, REFERENCED_TABLE_NAME
FROM information_schema.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = '<schema>'
AND REFERENCED_TABLE_NAME = '<table>'

para claves foráneas para <table>

También puede obtener UPDATE_RULE y DELETE_RULE si lo desea.

ChrisV
fuente
2
Personalmente, prefiero esta respuesta, ya que el uso de la tabla REFERENTIAL_CONSTRAINTS le proporciona la regla de actualización y cascada. +1
Luke Madhanga
¡Al descubrir una tabla, no debe olvidar que las claves externas se pueden establecer de AMBAS formas!
Codificador
11

Esta solución no solo mostrará todas las relaciones, sino también el nombre de restricción, que se requiere en algunos casos (p. Ej., Caída de contraint):

select
    concat(table_name, '.', column_name) as 'foreign key',
    concat(referenced_table_name, '.', referenced_column_name) as 'references',
    constraint_name as 'constraint name'
from
    information_schema.key_column_usage
where
    referenced_table_name is not null;

Si desea verificar las tablas en una base de datos específica, al final de la consulta agregue el nombre del esquema:

select
    concat(table_name, '.', column_name) as 'foreign key',
    concat(referenced_table_name, '.', referenced_column_name) as 'references',
    constraint_name as 'constraint name'
from
    information_schema.key_column_usage
where
    referenced_table_name is not null
    and table_schema = 'database_name';

Del mismo modo, para un nombre de columna específico, agregue

y table_name = 'table_name

al final de la consulta.

Inspirado en esta publicación aquí

Panayotis
fuente
7

Usar REFERENCED_TABLE_NAME no siempre funciona y puede ser un valor NULL. La siguiente consulta puede funcionar en su lugar:

select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME = '<table>';
Hazok
fuente
4

Una forma rápida de enumerar sus FK (referencias de clave externa) utilizando el

KEY_COLUMN_USAGE view:

SELECT CONCAT( table_name, '.',
column_name, ' -> ',
referenced_table_name, '.',
referenced_column_name ) AS list_of_fks
FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_SCHEMA = (your schema name here)
AND REFERENCED_TABLE_NAME is not null
ORDER BY TABLE_NAME, COLUMN_NAME;

Esta consulta asume que las restricciones y todas las tablas referenciadas y de referencia están en el mismo esquema.

Agrega tu propio comentario.

Fuente: el manual oficial de mysql.

Daniel Rodas
fuente
3

La solución que se me ocurrió es frágil; se basa en la convención de nomenclatura de django para claves externas.

USE information_schema;
tee mysql_output
SELECT * FROM TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_SCHEMA = 'database_name';
notee

Entonces, en el caparazón,

grep 'refs_tablename_id' mysql_output
Christian Oudard
fuente
2

Para buscar todas las tablas que contienen una clave foránea particular , comoemployee_id

SELECT DISTINCT TABLE_NAME 
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('employee_id')
AND TABLE_SCHEMA='table_name';
Anthony Vipond
fuente
2

Si también desea obtener el nombre de la columna de clave externa:

SELECT i.TABLE_SCHEMA, i.TABLE_NAME, 
       i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, 
       k.COLUMN_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME 
  FROM information_schema.TABLE_CONSTRAINTS i 
  LEFT JOIN information_schema.KEY_COLUMN_USAGE k 
       ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME 
 WHERE i.TABLE_SCHEMA = '<TABLE_NAME>' AND i.CONSTRAINT_TYPE = 'FOREIGN KEY' 
 ORDER BY i.TABLE_NAME;
omarjebari
fuente
Gracias gran solución! También necesitaba el nombre de la columna, para agregarlo: 'k.COLUMN_NAME'
Andreas