Come posso vedere tutte le chiavi esterne di una tabella o colonna?


Risposte:


764

Per un tavolo:

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

Per una colonna:

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

In sostanza, abbiamo modificato REFERENCED_TABLE_NAME con REFERENCED_COLUMN_NAME nella clausola where.


26
questo mi dà sempre un set vuoto, mentre la query proposta da Node di seguito funziona bene
Acute

7
@Acute: sei sicuro di chiedere la tabella corretta? Se la query di Node funziona, allora probabilmente stai chiedendo dell'altra direzione (cioè, le chiavi DA mytable, non le chiavi A mytable.) Ciò si aspettava che tu scrivessi '<table>' con il nome della tabella e senza '<' e '>' ?
Vinko Vrsalovic,

3
Sembra che io abbia frainteso la tua richiesta, perché stavo facendo una query per le chiavi che fanno riferimento DA <table> :) (sì, ho scritto il nome della tabella anziché "<table>" XD)
Acute,

4
A meno che non si sia sicuri che il nome della tabella sia univoco, è probabile che si desideri limitare anche la query a un determinato database. Modificare la clausola where in questo:where REFERENCED_TABLE_SCHEMA = 'mydatabase' and REFERENCED_TABLE_NAME = 'mytable'
user12345

Questo non funzionerà in caso di utente non root anche se l'utente dispone di tutte le autorizzazioni per il database
Deepak Ram

275

EDIT: Come sottolineato nei commenti, questa non è la risposta corretta alla domanda dei PO, ma è utile conoscere questo comando. Questa domanda è emersa su Google per quello che stavo cercando e ho pensato che avrei lasciato questa risposta per essere trovata dagli altri.

SHOW CREATE TABLE `<yourtable>`;

Ho trovato questa risposta qui: MySQL: mostra i vincoli sul comando tabelle

Avevo bisogno di questo perché volevo vedere come funzionava l'FK, piuttosto che vedere se esistesse o meno.


37
Questo mostra tutti i vincoli in <yourtable>, non tutti i vincoli che indicano <yourtable>.
Barmar,

18
Come dice @Barmar, questo è completamente sbagliato; mostrerà le chiavi estere del tavolo specificato, ma non mostrerà chiavi esterne che puntano TO tabella, che è ciò che la domanda chiede. Non ho idea di come questo abbia ottenuto 50 voti; Immagino che le persone siano finite qui quando stavano davvero cercando la risposta alla domanda opposta, trovando comunque la loro risposta qui e non si sono preoccupati di leggere la domanda originale (o addirittura il suo titolo) prima di votare.
Mark Amery,

2
@MarkAmery: questo è il primo risultato di display foreign keys mysqlGoogle, forse è per questo;)
Jigar

1
questo in realtà mostra tutti i vincoli esistenti, phpmyadmin ti mostrerà solo quello che punta alla tua tabella. sembra abbastanza buono da evitare duplicati con uno strumento ORM
william.eyidi,

3
Questo è quello che stavo cercando, quindi grazie per averlo pubblicato anche se non ha risposto alla domanda di OP. Non fa mai male sapere come guardare in entrambe le direzioni in una relazione!
Charles Wood,

75

Se si utilizza InnoDB e si definiscono gli FK, è possibile eseguire una query sul database information_schema, ad esempio:

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

15
in realtà, ciò indica la direzione sbagliata. quella query mostra tutte le chiavi esterne che puntano da 'mytable', non tutte le chiavi esterne che puntano a 'mytable'.
Christian Oudard,

1
Questo funziona meglio nel mio caso. Devo eliminare ogni vincolo di chiave esterna (e solo quelli) da una tabella per poter cambiare il motore MyISAM o NDB di InnoDB.
Kohányi Róbert,

Puoi ottenere le chiavi esterne in entrambe le direzioni dalla tabella REFERENTIAL_CONSTRAINTS - Ho aggiunto un'altra risposta con la query.
ChrisV,

45

Pubblicare una vecchia risposta per aggiungere alcune informazioni utili.

Ho avuto un problema simile, ma volevo anche vedere CONSTRAINT_TYPE insieme ai nomi di tabella e colonna REFERENCED. Così,

  1. Per vedere tutti gli FK nella tua tabella:

    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. Per vedere tutte le tabelle e gli FK nel tuo schema:

    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. Per vedere tutti gli FK nel tuo database:

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

Ricorda!

Questo utilizza il motore di archiviazione InnoDB. Se non riesci a visualizzare le chiavi esterne dopo averle aggiunte, probabilmente è perché le tue tabelle utilizzano MyISAM.

Controllare:

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

Per risolvere, usa questo:

ALTER TABLE `<yourtable>` ENGINE=InnoDB;

8
Queste query sono molto più veloci (da 2 secondi a 0,0015 secondi) se specifichi k.TABLE_SCHEMA = DATABASE () e k.TABLE_NAME = '<table>' sulla clausola WHERE, come documentato qui dev.mysql.com/doc/refman /5.5/it/…
guigouz

2
Bella risposta. Hai delle soluzioni per MyISAM?
Beau Bouchard,

2
Purtroppo MyISAM non supporta le chiavi esterne. dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
Andy

24

In alternativa alla risposta di Node, se si utilizza InnoDB e si definiscono FK, è possibile eseguire una query nel database information_schema, ad esempio:

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

per chiavi esterne da <table> o

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

per le chiavi esterne su <table>

Puoi anche ottenere UPDATE_RULE e DELETE_RULE se li desideri.


2
Personalmente preferisco questa risposta poiché l'uso della tabella REFERENTIAL_CONSTRAINTS ti dà la regola di aggiornamento e cascata. +1
Luke Madhanga,

Facendo scoperta su un tavolo non dovresti dimenticare che le chiavi esterne possono essere stabilite ENTRAMBI i modi!
Encoder

11

Questa soluzione mostrerà non solo tutte le relazioni, ma anche il nome del vincolo, che è richiesto in alcuni casi (es. 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;

Se si desidera controllare le tabelle in un database specifico, alla fine della query aggiungere il nome dello schema:

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

Allo stesso modo, per un nome di colonna specifico, aggiungere

e table_name = 'table_name

alla fine della query.

Ispirato da questo post qui


7

L'uso di REFERENCED_TABLE_NAME non sempre funziona e può essere un valore NULL. La seguente query può invece funzionare:

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

4

Un modo rapido per elencare i tuoi FK (riferimenti a chiave esterna) usando

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;

Questa query presuppone che i vincoli e tutte le tabelle di riferimento e di riferimento si trovino nello stesso schema.

Aggiungi il tuo commento.

Fonte: il manuale ufficiale di mysql.


3

La soluzione che ho trovato è fragile; si basa sulla convenzione di denominazione di Django per le chiavi esterne.

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

Quindi, nella shell,

grep 'refs_tablename_id' mysql_output

2

Per trovare tutte le tabelle contenenti una chiave esterna particolare comeemployee_id

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

2

Se vuoi anche ottenere il nome della colonna chiave esterna:

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;

Grazie ottima soluzione! Avevo bisogno anche del nome della colonna, per ottenerlo aggiungere: "k.COLUMN_NAME"
Andreas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.