Bagaimana cara melihat semua kunci asing ke tabel atau kolom?

567

Di MySQL, bagaimana saya mendapatkan daftar semua batasan kunci asing yang menunjuk ke tabel tertentu? kolom tertentu? Ini adalah hal yang sama dengan pertanyaan Oracle ini , tetapi untuk MySQL.

Christian Oudard
sumber

Jawaban:

764

Untuk Meja:

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

Untuk Kolom:

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

Pada dasarnya, kami mengubah REFERENCED_TABLE_NAME dengan REFERENCED_COLUMN_NAME dalam klausa where.

Vinko Vrsalovic
sumber
26
ini selalu memberi saya satu set kosong, sementara permintaan yang diajukan oleh Node di bawah berfungsi dengan baik
Acute
7
@ Acute: Apakah Anda yakin Anda bertanya tentang tabel yang benar? Jika kueri Node berfungsi, maka Anda kemungkinan bertanya tentang arah lain (mis., Kunci DARI mytable, bukan kunci TO mytable.) Ini mengharapkan Anda menulis '<table>' dengan nama tabel dan tanpa '<' dan '>' ?
Vinko Vrsalovic
3
Sepertinya saya salah mengerti permintaan Anda, karena saya meminta kunci yang merujuk dari <tabel> :) (ya, saya menulis nama tabel alih-alih "<tabel>" XD)
Acute
4
Kecuali Anda yakin nama tabel Anda unik, Anda mungkin ingin membatasi kueri Anda juga ke basis data tertentu. Ubah klausa di mana menjadi ini:where REFERENCED_TABLE_SCHEMA = 'mydatabase' and REFERENCED_TABLE_NAME = 'mytable'
user12345
Ini tidak akan bekerja jika bukan pengguna root meskipun pengguna memiliki semua izin ke database
Deepak Ram
275

EDIT: Seperti yang ditunjukkan dalam komentar, ini bukan jawaban yang benar untuk pertanyaan OPs, tetapi berguna untuk mengetahui perintah ini. Pertanyaan ini muncul di Google untuk apa yang saya cari, dan saya pikir saya akan meninggalkan jawaban ini untuk orang lain temukan.

SHOW CREATE TABLE `<yourtable>`;

Saya menemukan jawaban ini di sini: MySQL: menunjukkan batasan pada perintah tabel

Saya membutuhkan cara ini karena saya ingin melihat bagaimana fungsi FK, bukan hanya melihat apakah ada atau tidak.

CenterOrbit
sumber
37
Ini menunjukkan semua kendala di <yourtable>, tidak semua kendala yang mengarah ke <yourtable>.
Barmar
18
Seperti yang dikatakan @Barmar, ini sepenuhnya salah; ia akan menampilkan kunci asing milik meja tertentu, tetapi tidak akan menampilkan kunci asing menunjuk ke meja, yang adalah apa pertanyaan meminta. Tidak tahu bagaimana ini mendapat 50 upvotes; Saya kira orang-orang berakhir di sini ketika mereka benar-benar mencari jawaban untuk pertanyaan sebaliknya, tetap menemukan jawaban mereka di sini, dan tidak repot-repot membaca pertanyaan asli (atau bahkan judulnya) sebelum melakukan upvoting.
Mark Amery
2
@MarkAmery: ini adalah hasil pertama display foreign keys mysqldi google, mungkin itu sebabnya;)
Jigar
1
thisi benar-benar menunjukkan semua kendala yang ada, phpmyadmin hanya akan menunjukkan kepada Anda yang menunjuk ke tabel Anda. tampaknya cukup baik untuk menghindari duplikat dengan alat ORM
william.eyidi
3
Ini yang saya cari, jadi terima kasih sudah mempostingnya meskipun tidak menjawab pertanyaan OP. Tidak ada salahnya untuk mengetahui cara melihat ke dua arah dalam suatu hubungan!
Charles Wood
75

Jika Anda menggunakan InnoDB dan mendefinisikan FK, Anda dapat menanyakan database information_schema misalnya:

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';
Node
sumber
15
sebenarnya, itu menunjukkan arah yang salah. kueri itu menunjukkan semua kunci asing yang menunjuk DARI 'mytable', tidak semua kunci asing menunjuk ke 'mytable'.
Christian Oudard
1
Yang ini berfungsi lebih baik dalam kasus saya. Saya perlu menghapus setiap batasan kunci asing (dan hanya itu) dari sebuah tabel untuk dapat mengubah mesin InnoDB MyISAM atau NDB.
Kohányi Róbert
Anda bisa mendapatkan kunci asing di kedua arah dari tabel REFERENTIAL_CONSTRAINTS - Saya telah menambahkan jawaban lain dengan kueri.
ChrisV
45

Posting pada jawaban lama untuk menambahkan beberapa informasi bermanfaat.

Saya memiliki masalah yang sama, tetapi saya juga ingin melihat CONSTRAINT_TYPE bersama dengan tabel dan kolom nama yang direferensikan. Begitu,

  1. Untuk melihat semua FK di tabel Anda:

    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. Untuk melihat semua tabel dan FK di skema Anda:

    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. Untuk melihat semua FK di database Anda:

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

Ingat!

Ini menggunakan mesin penyimpanan InnoDB. Jika Anda tampaknya tidak bisa mendapatkan kunci asing untuk muncul setelah menambahkannya, itu mungkin karena tabel Anda menggunakan MyISAM.

Untuk memeriksa:

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

Untuk memperbaikinya, gunakan ini:

ALTER TABLE `<yourtable>` ENGINE=InnoDB;
Andy
sumber
8
Kueri tersebut berjalan lebih cepat (dari 2 detik hingga 0,0015 detik) jika Anda menentukan k.TABLE_SCHEMA = DATABASE () dan k.TABLE_NAME = '<table>' pada klausa WHERE, seperti yang didokumentasikan di sini dev.mysql.com/doc/refman /5.5/en/…
guigouz
2
jawaban yang bagus Apakah Anda punya solusi untuk MyISAM?
Beau Bouchard
2
Sayangnya, MyISAM tidak mendukung kunci asing. dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
Andy
24

Sebagai alternatif untuk jawaban Node, jika Anda menggunakan InnoDB dan mendefinisikan FK, Anda dapat menanyakan database information_schema misalnya:

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

untuk kunci asing dari <table>, atau

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

untuk kunci asing ke <tabel>

Anda juga bisa mendapatkan UPDATE_RULE dan DELETE_RULE jika Anda menginginkannya.

ChrisV
sumber
2
Saya pribadi lebih suka jawaban ini karena menggunakan tabel REFERENTIAL_CONSTRAINTS memberi Anda aturan pembaruan dan kaskade. +1
Luke Madhanga
Melakukan penemuan tentang tabel Anda tidak boleh lupa bahwa kunci asing dapat dibuat KEDUA cara!
Encoder
11

Solusi ini tidak hanya akan menampilkan semua relasi tetapi juga nama kendala, yang diperlukan dalam beberapa kasus (mis. 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;

Jika Anda ingin memeriksa tabel dalam database tertentu, di akhir kueri tambahkan nama skema:

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

Demikian juga, untuk nama kolom tertentu, tambahkan

dan table_name = 'table_name

di akhir kueri.

Terinspirasi oleh pos ini di sini

Panayotis
sumber
7

Menggunakan REFERENCED_TABLE_NAME tidak selalu berfungsi dan bisa menjadi nilai NULL. Sebaliknya, kueri berikut dapat berfungsi:

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

Cara cepat untuk mendaftar FK Anda (referensi Kunci Asing) menggunakan

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;

Kueri ini mengasumsikan bahwa kendala dan semua tabel referensi dan referensi berada dalam skema yang sama.

Tambahkan komentar Anda sendiri.

Sumber: manual resmi mysql.

Daniel Rodas
sumber
3

Solusi yang saya temukan adalah rapuh; itu bergantung pada konvensi penamaan Django untuk kunci asing.

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

Kemudian, di shell,

grep 'refs_tablename_id' mysql_output
Christian Oudard
sumber
2

Untuk menemukan semua tabel yang berisi kunci asing tertentu sepertiemployee_id

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

Jika Anda juga ingin mendapatkan nama kolom kunci asing:

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
sumber
Terima kasih solusi hebat! Saya membutuhkan nama kolom juga, untuk menambahkannya: 'k.COLUMN_NAME'
Andreas