Wie sehe ich alle Fremdschlüssel für eine Tabelle oder Spalte?


Antworten:


764

Für eine Tabelle:

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

Für eine Kolumne:

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

Grundsätzlich haben wir REFERENCED_TABLE_NAME in der where-Klausel durch REFERENCED_COLUMN_NAME geändert.


26
Dies gibt mir immer einen leeren Satz, während die von Node unten vorgeschlagene Abfrage gut funktioniert
Acute

7
@Acute: Bist du sicher, dass du nach der richtigen Tabelle fragst? Wenn die Abfrage des Knotens funktioniert, fragen Sie wahrscheinlich nach der anderen Richtung (dh nach den Schlüsseln von mytable, nicht nach mytable). In dieser Erwartung haben Sie '<table>' mit dem Tabellennamen und ohne '<' und '>' geschrieben. ?
Vinko Vrsalovic

3
Scheint, als hätte ich Ihre Abfrage falsch verstanden, weil ich nach Schlüsseln gefragt habe, die auf FROM <Tabelle> verweisen :) :) (Ja, ich habe Tabellennamen anstelle von "<Tabelle>" XD geschrieben)
Akut

4
Sofern Sie nicht sicher sind, dass Ihr Tabellenname eindeutig ist, möchten Sie Ihre Abfrage wahrscheinlich auch auf eine bestimmte Datenbank beschränken. Ändern Sie die where-Klausel in folgende:where REFERENCED_TABLE_SCHEMA = 'mydatabase' and REFERENCED_TABLE_NAME = 'mytable'
user12345

Dies funktioniert nicht bei Nicht-Root-Benutzern, obwohl der Benutzer alle Berechtigungen für die Datenbank hat
Deepak Ram

275

BEARBEITEN: Wie in den Kommentaren erwähnt, ist dies nicht die richtige Antwort auf die Frage des OP, aber es ist nützlich, diesen Befehl zu kennen. Diese Frage tauchte in Google für das auf, wonach ich suchte, und dachte, ich würde diese Antwort den anderen überlassen, um sie zu finden.

SHOW CREATE TABLE `<yourtable>`;

Ich habe diese Antwort hier gefunden: MySQL: show Einschränkungen für Tabellenbefehl

Ich brauchte diesen Weg, weil ich sehen wollte, wie der FK funktioniert, anstatt nur zu sehen, ob er existiert oder nicht.


37
Dies zeigt alle Einschränkungen in <yourtable>, nicht alle Einschränkungen, auf die verwiesen wird <yourtable>.
Barmar

18
Wie @Barmar sagt, ist dies völlig falsch; Es werden die Fremdschlüssel angezeigt, die zur angegebenen Tabelle gehören, aber keine Fremdschlüssel, die auf die Tabelle verweisen. Dies ist die Frage, nach der gefragt wird. Keine Ahnung, wie das zu 50 Upvotes kam; Ich denke, die Leute sind hier gelandet, als sie wirklich nach der Antwort auf die entgegengesetzte Frage suchten, ihre Antwort hier sowieso fanden und sich nicht die Mühe machten, die ursprüngliche Frage (oder sogar den Titel) vor dem Upvoting zu lesen.
Mark Amery

2
@ MarkAmery: Dies ist das erste Ergebnis von display foreign keys mysqlin Google, vielleicht deshalb;)
Jigar

1
thisi zeigt tatsächlich alle vorhandenen Einschränkungen an, phpmyadmin zeigt Ihnen nur diejenige an, die auf Ihre Tabelle zeigt. scheint gut genug zu sein, um Duplikate mit einem ORM-Tool zu vermeiden
william.eyidi

3
Dies ist, wonach ich gesucht habe. Vielen Dank, dass Sie es veröffentlicht haben, obwohl es die Frage von OP nicht beantwortet hat. Es tut nie weh zu wissen, wie man in einer Beziehung in beide Richtungen schaut!
Charles Wood

75

Wenn Sie InnoDB verwenden und FKs definieren, können Sie die Datenbank information_schema abfragen, z.

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
Eigentlich weist das in die falsche Richtung. Diese Abfrage zeigt alle Fremdschlüssel, die von 'mytable' zeigen, nicht alle Fremdschlüssel, die auf 'mytable' zeigen.
Christian Oudard

1
Dieser funktioniert in meinem Fall besser. Ich muss jede Fremdschlüsseleinschränkung (und nur diese) aus einer Tabelle löschen, um die InnoDB-Engine MyISAM oder NDB ändern zu können.
Kohányi Róbert

Sie können Fremdschlüssel in beide Richtungen aus der Tabelle REFERENTIAL_CONSTRAINTS abrufen. Ich habe der Abfrage eine weitere Antwort hinzugefügt.
ChrisV

45

Veröffentlichen Sie eine alte Antwort, um einige nützliche Informationen hinzuzufügen.

Ich hatte ein ähnliches Problem, wollte aber auch CONSTRAINT_TYPE zusammen mit den Tabellen- und Spaltennamen REFERENCED sehen. Damit,

  1. So zeigen Sie alle FKs in Ihrer Tabelle an:

    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. So zeigen Sie alle Tabellen und FKs in Ihrem Schema an:

    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. So zeigen Sie alle FKs in Ihrer Datenbank an:

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

Merken!

Dies verwendet die InnoDB-Speicher-Engine. Wenn nach dem Hinzufügen keine Fremdschlüssel angezeigt werden, liegt dies wahrscheinlich daran, dass Ihre Tabellen MyISAM verwenden.

Überprüfen:

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

Verwenden Sie zum Beheben Folgendes:

ALTER TABLE `<yourtable>` ENGINE=InnoDB;

8
Diese Abfragen werden viel schneller ausgeführt (von 2 Sekunden bis 0,0015 Sekunden), wenn Sie in der WHERE-Klausel k.TABLE_SCHEMA = DATABASE () und k.TABLE_NAME = '<table>' angeben, wie hier dev.mysql.com/doc/refman
Guigouz

2
gute Antwort. Haben Sie Lösungen für MyISAM?
Beau Bouchard

2
MyISAM unterstützt leider keine Fremdschlüssel. dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
Andy

24

Wenn Sie als Alternative zur Antwort von Node InnoDB verwenden und FKs definieren, können Sie die Datenbank information_schema abfragen, z.

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

für Fremdschlüssel aus <Tabelle> oder

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

für Fremdschlüssel zu <Tabelle>

Sie können auch UPDATE_RULE und DELETE_RULE abrufen, wenn Sie dies möchten.


2
Ich persönlich bevorzuge diese Antwort, da die Verwendung der Tabelle REFERENTIAL_CONSTRAINTS Ihnen die Aktualisierungs- und Kaskadenregel liefert. +1
Luke Madhanga

Wenn Sie eine Tabelle entdecken, sollten Sie nicht vergessen, dass Fremdschlüssel auf BEIDE Arten eingerichtet werden können!
Encoder

11

Diese Lösung zeigt nicht nur alle Beziehungen an, sondern auch den in einigen Fällen erforderlichen Einschränkungsnamen (z. B. 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;

Wenn Sie Tabellen in einer bestimmten Datenbank überprüfen möchten, fügen Sie am Ende der Abfrage den Schemanamen hinzu:

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

Fügen Sie für einen bestimmten Spaltennamen ebenfalls hinzu

und table_name = 'table_name

am Ende der Abfrage.

Inspiriert von diesem Beitrag hier


7

Die Verwendung von REFERENCED_TABLE_NAME funktioniert nicht immer und kann ein NULL-Wert sein. Die folgende Abfrage kann stattdessen funktionieren:

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

4

Eine schnelle Möglichkeit, Ihre FKs (Fremdschlüsselreferenzen) mithilfe von aufzulisten

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;

Bei dieser Abfrage wird davon ausgegangen, dass sich die Einschränkungen und alle referenzierten und referenzierenden Tabellen im selben Schema befinden.

Fügen Sie Ihren eigenen Kommentar hinzu.

Quelle: das offizielle MySQL-Handbuch.


3

Die Lösung, die ich gefunden habe, ist fragil. Es basiert auf der Namenskonvention von Django für Fremdschlüssel.

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

Dann in der Schale,

grep 'refs_tablename_id' mysql_output

2

So finden Sie alle Tabellen, die einen bestimmten Fremdschlüssel enthalten, zemployee_id

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

2

Wenn Sie auch den Namen der Fremdschlüsselspalte erhalten möchten:

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;

Danke tolle Lösung! Ich brauchte auch den Spaltennamen, um ihn hinzuzufügen: 'k.COLUMN_NAME'
Andreas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.