Jak wyświetlić wszystkie klucze obce do tabeli lub kolumny?

567

W MySQL, w jaki sposób uzyskać listę wszystkich ograniczeń kluczy obcych wskazujących na określoną tabelę? konkretna kolumna? To jest to samo, co pytanie Oracle , ale w przypadku MySQL.

Christian Oudard
źródło

Odpowiedzi:

764

Do stołu:

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

Dla kolumny:

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

Zasadniczo zmieniliśmy REFERENCED_TABLE_NAME na REFERENCED_COLUMN_NAME w klauzuli where.

Vinko Vrsalovic
źródło
26
to zawsze daje mi pusty zestaw, podczas gdy zapytanie zaproponowane przez Node poniżej działa dobrze
Acute
7
@ Ostre: Czy na pewno pytasz o właściwy stół? Jeśli zapytanie Node działa, to prawdopodobnie pytasz o inny kierunek (tj. Klucze od mytable, a nie klucze do mytable.) Oczekiwanie, że napisałeś „<table>” z nazwą tabeli i bez „<” i „>” ?
Vinko Vrsalovic
3
Wygląda na to, że źle zrozumiałem twoje zapytanie, ponieważ pytałem o klucze odwołujące się z <table> :) (tak, napisałem nazwę tabeli zamiast "<table>" XD)
Acute
4
Jeśli nie masz pewności, że nazwa tabeli jest unikalna, prawdopodobnie będziesz chciał ograniczyć zapytanie również do konkretnej bazy danych. Zmień klauzulę where na to:where REFERENCED_TABLE_SCHEMA = 'mydatabase' and REFERENCED_TABLE_NAME = 'mytable'
użytkownik12345
To nie zadziała w przypadku użytkownika innego niż root, mimo że użytkownik ma wszystkie uprawnienia do bazy danych
Deepak Ram,
275

EDYCJA: Jak wskazano w komentarzach, nie jest to poprawna odpowiedź na pytanie PO, ale warto znać to polecenie. To pytanie pojawiło się w Google, czego szukałem, i pomyślałem, że zostawię tę odpowiedź innym.

SHOW CREATE TABLE `<yourtable>`;

Znalazłem tę odpowiedź tutaj: MySQL: pokaż ograniczenia komendy tabel

Potrzebowałem tego, ponieważ chciałem zobaczyć, jak działa FK, a nie tylko sprawdzić, czy istnieje.

CenterOrbit
źródło
37
Pokazuje wszystkie ograniczenia <yourtable>, a nie wszystkie, które wskazują <yourtable>.
Barmar
18
Jak mówi @Barmar, jest to całkowicie błędne; pokaże zagranicznych klucze należące do określonej tabeli, ale nie pokaże kluczy obcych, wskazując DO tabeli, która jest co kwestia prosi. Nie mam pojęcia, jak to zyskało 50 głosów pozytywnych; Sądzę, że ludzie znaleźli się tutaj, kiedy naprawdę szukali odpowiedzi na pytanie przeciwne, i tak znaleźli tutaj swoją odpowiedź i nie zawracali sobie głowy czytaniem oryginalnego pytania (lub nawet jego tytułu) przed głosowaniem.
Mark Amery
2
@MarkAmery: to pierwszy wynik display foreign keys mysqlGoogle, być może dlatego;)
Jigar
1
thisi faktycznie pokazuje wszystkie istniejące ograniczenia, phpmyadmin pokaże ci tylko ten, który wskazuje na twój stół. wydaje się wystarczająco dobry, aby uniknąć duplikatów za pomocą narzędzia ORM
william.eyidi
3
Właśnie tego szukałem, więc dziękuję za opublikowanie go, mimo że nie odpowiedział na pytanie OP. Nigdy nie boli wiedzieć, jak patrzeć w obu kierunkach w związku!
Charles Wood,
75

Jeśli używasz InnoDB i zdefiniowałeś FK, możesz zapytać o bazę danych information_schema, np .:

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';
Węzeł
źródło
15
w rzeczywistości wskazuje to zły kierunek. zapytanie to pokazuje wszystkie klucze obce wskazujące na „mytable”, a nie wszystkie klucze obce wskazujące na „mytable”.
Christian Oudard
1
Ten działa lepiej w moim przypadku. Muszę usunąć każde ograniczenie klucza obcego (i tylko te) z tabeli, aby móc zmienić silnik InISDB MyISAM lub NDB.
Kohányi Róbert
Możesz uzyskać klucze obce w obu kierunkach z tabeli REFERENTIAL_CONSTRAINTS - dodałem kolejną odpowiedź do zapytania.
ChrisV,
45

Publikowanie starej odpowiedzi w celu dodania użytecznych informacji.

Miałem podobny problem, ale chciałem też zobaczyć CONSTRAINT_TYPE wraz z tabelą REFERENCED i nazwami kolumn. Więc,

  1. Aby zobaczyć wszystkie FK w tabeli:

    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. Aby zobaczyć wszystkie tabele i FK w schemacie:

    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. Aby zobaczyć wszystkie FK w bazie danych:

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

Zapamiętaj!

Wykorzystuje to silnik pamięci InnoDB. Jeśli po dodaniu ich nie możesz wyświetlić żadnych obcych kluczy, prawdopodobnie oznacza to, że Twoje tabele używają MyISAM.

Sprawdzić:

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

Aby to naprawić, użyj tego:

ALTER TABLE `<yourtable>` ENGINE=InnoDB;
Andy
źródło
8
Te zapytania działają znacznie szybciej (od 2 sekund do 0,0015 sekund), jeśli podasz k.TABLE_SCHEMA = DATABASE () i k.TABLE_NAME = '<table>' w klauzuli WHERE, jak udokumentowano tutaj dev.mysql.com/doc/refman /5.5/en/…
guigouz
2
świetna odpowiedź. Czy masz jakieś rozwiązania dla MyISAM?
Beau Bouchard
2
MyISAM niestety nie obsługuje kluczy obcych. dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
Andy
24

Alternatywnie do odpowiedzi Węzła, jeśli używasz InnoDB i zdefiniowałeś FK, możesz zapytać do bazy danych schemat_informacyjny np .:

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

dla kluczy obcych z <tabela> lub

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

dla kluczy obcych do <tabela>

Możesz także uzyskać UPDATE_RULE i DELETE_RULE, jeśli chcesz.

ChrisV
źródło
2
Ja osobiście wolę tę odpowiedź, ponieważ użycie tabeli REFERENTIAL_CONSTRAINTS daje aktualizację i regułę kaskadową. +1
Luke Madhanga
Odkrywając tabelę, nie powinieneś zapominać, że klucze obce można ustalić OBU sposobami!
Koder
11

To rozwiązanie wyświetli nie tylko wszystkie relacje, ale także nazwę ograniczenia, która jest wymagana w niektórych przypadkach (np. Ograniczenie upuszczenia):

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;

Jeśli chcesz sprawdzić tabele w określonej bazie danych, na końcu zapytania dodaj nazwę schematu:

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

Podobnie, dla konkretnej nazwy kolumny dodaj

i nazwa_tabeli = 'nazwa_tabeli

na końcu zapytania.

Inspirowany tym postem tutaj

Panayotis
źródło
7

Korzystanie z REFERENCED_TABLE_NAME nie zawsze działa i może mieć wartość NULL. Zamiast tego może działać następujące zapytanie:

select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME = '<table>';
Hazok
źródło
4

Szybki sposób na wyświetlenie listy FK (odniesienia do klucza obcego) za pomocą

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;

W tym zapytaniu założono, że ograniczenia oraz wszystkie tabele, do których istnieją odniesienia i tabele, są w tym samym schemacie.

Dodaj swój komentarz.

Źródło: oficjalny podręcznik mysql.

Daniel Rodas
źródło
3

Rozwiązanie, które wymyśliłem, jest kruche; opiera się na konwencji nazewnictwa django dla kluczy obcych.

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

Następnie w skorupce

grep 'refs_tablename_id' mysql_output
Christian Oudard
źródło
2

Aby znaleźć wszystkie tabele zawierające określony klucz obcy, taki jakemployee_id

SELECT DISTINCT TABLE_NAME 
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('employee_id')
AND TABLE_SCHEMA='table_name';
Anthony Vipond
źródło
2

Jeśli chcesz również uzyskać nazwę kolumny klucza obcego:

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
źródło
Dzięki świetne rozwiązanie! Potrzebowałem też nazwy kolumny, aby ją dodać: „k.COLUMN_NAME”
Andreas