Comment voir toutes les clés étrangères d'une table ou d'une colonne?

567

Dans MySQL, comment obtenir une liste de toutes les contraintes de clé étrangère pointant vers une table particulière? une colonne particulière? C'est la même chose que cette question Oracle , mais pour MySQL.

Christian Oudard
la source

Réponses:

764

Pour une table:

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

Pour une colonne:

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

Fondamentalement, nous avons modifié REFERENCED_TABLE_NAME par REFERENCED_COLUMN_NAME dans la clause where.

Vinko Vrsalovic
la source
26
cela me donne toujours un ensemble vide, tandis que la requête proposée par Node ci-dessous fonctionne bien
Acute
7
@Acute: Êtes-vous sûr de poser des questions sur le bon tableau? Si la requête de Node fonctionne, alors vous vous posez probablement des questions sur l'autre sens (c'est-à-dire les clés DE ma table, pas les clés DE ma table). ?
Vinko Vrsalovic
3
On dirait que j'ai mal compris que vous interrogiez, parce que je demandais des clés faisant référence à la <table> :) (oui, j'ai écrit le nom de la table au lieu de "<table>" XD)
Aigu
4
Sauf si vous êtes sûr que le nom de votre table est unique, vous souhaiterez probablement restreindre votre requête à une base de données particulière également. Remplacez la clause where par ceci:where REFERENCED_TABLE_SCHEMA = 'mydatabase' and REFERENCED_TABLE_NAME = 'mytable'
user12345
Cela ne fonctionnera pas dans le cas d'un utilisateur non root même si l'utilisateur a toutes les autorisations sur la base de données
Deepak Ram
275

EDIT: Comme indiqué dans les commentaires, ce n'est pas la bonne réponse à la question OP, mais il est utile de connaître cette commande. Cette question est apparue dans Google pour ce que je cherchais, et a pensé que je laisserais cette réponse aux autres.

SHOW CREATE TABLE `<yourtable>`;

J'ai trouvé cette réponse ici: MySQL: commande afficher les contraintes sur les tables

J'avais besoin de cette façon parce que je voulais voir comment le FK fonctionnait, plutôt que de simplement voir s'il existait ou non.

CenterOrbit
la source
37
Cela montre toutes les contraintes dans <yourtable>, pas toutes les contraintes qui pointent vers <yourtable>.
Barmar
18
Comme le dit @Barmar, c'est tout à fait faux; il montrera les clés étrangères appartenant à la table spécifiée, mais ne montrera pas les clés étrangères pointant À la table, ce qui est la question demande. Je ne sais pas comment cela a obtenu 50 votes positifs; Je suppose que les gens se sont retrouvés ici alors qu'ils cherchaient vraiment la réponse à la question opposée, ont trouvé leur réponse ici de toute façon et n'ont pas pris la peine de lire la question d'origine (ou même son titre) avant de voter.
Mark Amery
2
@MarkAmery: c'est le premier résultat de display foreign keys mysqlgoogle, c'est peut-être pour ça;)
Jigar
1
ceci montre en fait toutes les contraintes qui existent, phpmyadmin ne vous montrera que celle pointant vers votre table. semble assez bon pour éviter les doublons avec un outil ORM
william.eyidi
3
C'est ce que je cherchais, alors merci de l'avoir posté même s'il n'a pas répondu à la question d'OP. Jamais mal de savoir regarder dans les deux sens dans une relation!
Charles Wood
75

Si vous utilisez InnoDB et définissez des FK, vous pouvez interroger la base de données information_schema, par exemple:

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';
Nœud
la source
15
en fait, cela indique la mauvaise direction. cette requête affiche toutes les clés étrangères pointant DEPUIS 'ma table', pas toutes les clés étrangères pointant vers 'ma table'.
Christian Oudard
1
Celui-ci fonctionne mieux dans mon cas. J'ai besoin de supprimer chaque contrainte de clé étrangère (et seulement celles) d'une table pour pouvoir changer le moteur InnoDB MyISAM ou NDB.
Kohányi Róbert
Vous pouvez obtenir des clés étrangères dans les deux sens à partir de la table REFERENTIAL_CONSTRAINTS - J'ai ajouté une autre réponse à la requête.
ChrisV
45

Publier sur une ancienne réponse pour ajouter des informations utiles.

J'ai eu un problème similaire, mais je voulais également voir le CONSTRAINT_TYPE avec les noms de table et de colonne REFERENCED. Donc,

  1. Pour voir tous les FK dans votre tableau:

    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. Pour voir toutes les tables et tous les FK de votre schéma:

    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. Pour voir tous les FK dans votre base de données:

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

Rappelles toi!

Cela utilise le moteur de stockage InnoDB. Si vous n'arrivez pas à faire apparaître de clés étrangères après les avoir ajoutées, c'est probablement parce que vos tables utilisent MyISAM.

Vérifier:

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

Pour corriger, utilisez ceci:

ALTER TABLE `<yourtable>` ENGINE=InnoDB;
Andy
la source
8
Ces requêtes s'exécutent beaucoup plus rapidement (de 2 secondes à 0,0015 secondes) si vous spécifiez k.TABLE_SCHEMA = DATABASE () et k.TABLE_NAME = '<table>' sur la clause WHERE, comme indiqué
guigouz
2
très bonne réponse. Avez-vous des solutions pour MyISAM?
Beau Bouchard
2
Malheureusement, MyISAM ne prend pas en charge les clés étrangères. dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
Andy
24

Comme alternative à la réponse de Node, si vous utilisez InnoDB et définissez des FK, vous pouvez interroger la base de données information_schema, par exemple:

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

pour les clés étrangères de <table>, ou

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

pour les clés étrangères à <table>

Vous pouvez également obtenir les UPDATE_RULE et DELETE_RULE si vous les souhaitez.

ChrisV
la source
2
Personnellement, je préfère cette réponse car l'utilisation de la table REFERENTIAL_CONSTRAINTS vous donne la règle de mise à jour et de cascade. +1
Luke Madhanga
En faisant la découverte d'une table, vous ne devez pas oublier que les clés étrangères peuvent être établies DES DEUX façons!
Encodeur
11

Cette solution affichera non seulement toutes les relations mais aussi le nom de la contrainte, ce qui est nécessaire dans certains cas (par exemple drop 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 vous souhaitez vérifier les tables dans une base de données spécifique, à la fin de la requête, ajoutez le nom du schéma:

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

De même, pour un nom de colonne spécifique, ajoutez

et table_name = 'table_name

à la fin de la requête.

Inspiré par ce post ici

Panayotis
la source
7

L'utilisation de REFERENCED_TABLE_NAME ne fonctionne pas toujours et peut être une valeur NULL. La requête suivante peut fonctionner à la place:

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

Un moyen rapide de répertorier vos FK (références de clé étrangère) en utilisant le

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;

Cette requête suppose que les contraintes et toutes les tables référencées et référençantes sont dans le même schéma.

Ajoutez votre propre commentaire.

Source: le manuel mysql officiel.

Daniel Rodas
la source
3

La solution que j'ai trouvée est fragile; il s'appuie sur la convention de dénomination de django pour les clés étrangères.

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

Ensuite, dans la coquille,

grep 'refs_tablename_id' mysql_output
Christian Oudard
la source
2

Pour rechercher toutes les tables contenant une clé étrangère particulière telle queemployee_id

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

Si vous souhaitez également obtenir le nom de la colonne de clé étrangère:

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
la source
Merci grande solution! J'avais également besoin du nom de la colonne, pour l'obtenir, ajoutez: 'k.COLUMN_NAME'
Andreas