ฉันจะดูกุญแจต่างประเทศทั้งหมดในตารางหรือคอลัมน์ได้อย่างไร


567

ใน MySQL ฉันจะรับรายการข้อ จำกัด คีย์ต่างประเทศทั้งหมดที่ชี้ไปยังตารางที่ระบุได้อย่างไร คอลัมน์ใดคอลัมน์หนึ่ง นี่คือสิ่งเดียวกันกับคำถาม Oracle นี้แต่สำหรับ MySQL

คำตอบ:


764

สำหรับตาราง:

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

สำหรับคอลัมน์:

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

โดยพื้นฐานแล้วเราเปลี่ยน REFERENCED_TABLE_NAME ด้วย REFERENCED_COLUMN_NAME ในส่วนคำสั่ง


26
สิ่งนี้จะทำให้ฉันว่างเสมอในขณะที่แบบสอบถามที่เสนอโดยโหนดด้านล่างใช้งานได้ดี
Acute

7
@ น่าเชื่อถือ: คุณแน่ใจหรือไม่ว่าคุณกำลังถามเกี่ยวกับตารางที่ถูกต้อง? หากการสืบค้นของโหนดทำงานคุณอาจถามเกี่ยวกับทิศทางอื่น (เช่นแป้นจาก mytable ไม่ใช่แป้นไปที่ mytable) สิ่งนี้คาดว่าคุณจะเขียน '<table>' ด้วยชื่อตารางและไม่มี '<' และ '>' ?
Vinko Vrsalovic

3
ดูเหมือนว่าฉันเข้าใจผิดคุณสืบค้นเพราะฉันกำลังค้นหาคีย์ที่อ้างอิงจาก <table> :) (ใช่ฉันเขียนชื่อตารางแทน "<table>" XD)
Acute

4
หากคุณไม่แน่ใจว่าชื่อตารางของคุณไม่เหมือนใครคุณอาจต้องการ จำกัด การสืบค้นของคุณลงในฐานข้อมูลเฉพาะเช่นกัน เปลี่ยนส่วนคำสั่งเป็น:where REFERENCED_TABLE_SCHEMA = 'mydatabase' and REFERENCED_TABLE_NAME = 'mytable'
user12345

สิ่งนี้จะไม่ทำงานในกรณีของผู้ใช้ที่ไม่ใช่รูทแม้ว่าผู้ใช้จะมีสิทธิ์ในฐานข้อมูลทั้งหมด
Deepak Ram

275

แก้ไข: ตามที่ระบุไว้ในความคิดเห็นนี้ไม่ใช่คำตอบที่ถูกต้องสำหรับคำถาม OPs แต่มันมีประโยชน์ที่จะรู้คำสั่งนี้ คำถามนี้ปรากฏใน Google สำหรับสิ่งที่ฉันกำลังมองหาและคิดว่าฉันจะทิ้งคำตอบนี้เพื่อให้คนอื่นหา

SHOW CREATE TABLE `<yourtable>`;

ฉันพบคำตอบนี้ที่นี่: MySQL: แสดงข้อ จำกัด ในคำสั่ง tables

ฉันต้องการวิธีนี้เพราะฉันต้องการดูว่า FK ทำงานอย่างไรแทนที่จะดูว่ามันมีอยู่จริงหรือไม่


37
แสดงให้เห็นว่าทั้งหมดนี้ข้อ จำกัด ใน<yourtable>ไม่ได้ทุกข้อ จำกัด <yourtable>ที่ชี้ไปที่
Barmar

18
@Barmar พูดว่านี่เป็นสิ่งที่ผิดทั้งหมด มันจะแสดงกุญแจต่างประเทศที่เป็นของตารางที่ระบุ แต่จะไม่แสดงกุญแจต่างประเทศที่ชี้ไปที่ตารางซึ่งเป็นคำถามที่ถาม ไม่รู้เลยว่าจะมี 50 upvotes อย่างไร ฉันเดาว่าผู้คนมาที่นี่เมื่อจริง ๆ แล้วพวกเขากำลังมองหาคำตอบสำหรับคำถามตรงข้ามพบคำตอบของพวกเขาที่นี่ต่อไปและไม่ต้องกังวลกับการอ่านคำถามดั้งเดิม (หรือแม้แต่ชื่อเรื่อง) ก่อนการถอน
Mark Amery

2
@MarkAmery: นี้เป็นผลแรกของdisplay foreign keys mysqlใน Google, อาจเป็นได้ว่าเป็นเหตุผลที่;)
Jigar

1
นี่แสดงให้เห็นถึงข้อ จำกัด ทั้งหมดที่มีอยู่จริง phpmyadmin จะแสดงให้คุณเห็นเพียงชี้ไปที่ตารางของคุณ ดูดีพอที่จะหลีกเลี่ยงการซ้ำซ้อนด้วยเครื่องมือ ORM
william.eyidi

3
นี่คือสิ่งที่ฉันกำลังมองหาดังนั้นขอบคุณสำหรับการโพสต์มันแม้ว่ามันจะไม่ได้ตอบคำถามของ OP ไม่เคยเจ็บปวดที่จะรู้วิธีดูทั้งสองทิศทางในความสัมพันธ์!
Charles Wood

75

หากคุณใช้ InnoDB และกำหนด FK คุณสามารถสืบค้นฐานข้อมูล information_schema เช่น:

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
จริง ๆ แล้วมันชี้ไปในทิศทางที่ผิด คำค้นหานั้นแสดงคีย์ต่างประเทศทั้งหมดที่ชี้จาก 'mytable' ไม่ใช่คีย์ต่างประเทศทั้งหมดที่ชี้ไปที่ 'mytable'
Christian Oudard

1
อันนี้ใช้ได้ดีกว่าในกรณีของฉัน ฉันต้องวางข้อ จำกัด กุญแจต่างประเทศทุกตัว (และเฉพาะที่) จากตารางเพื่อให้สามารถเปลี่ยนเครื่องยนต์ InnoDB MyISAM หรือ NDB
KohányiRóbert

คุณสามารถรับคีย์ต่างประเทศได้จากทั้งสองทิศทางจากตาราง REFERENTIAL_CONSTRAINTS - ฉันได้เพิ่มคำตอบอื่นด้วยแบบสอบถาม
ChrisV

45

โพสต์คำตอบเก่าเพื่อเพิ่มข้อมูลที่เป็นประโยชน์

ฉันมีปัญหาที่คล้ายกัน แต่ฉันต้องการเห็น CONSTRAINT_TYPE พร้อมกับชื่อตารางและคอลัมน์ที่อ้างอิง ดังนั้น,

  1. หากต้องการดู FK ทั้งหมดในตารางของคุณ:

    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. หากต้องการดูตารางและ FK ทั้งหมดในสคีมาของคุณ:

    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. ในการดู FK ทั้งหมดในฐานข้อมูลของคุณ:

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

จำไว้!

นี่คือการใช้เครื่องมือจัดเก็บข้อมูล InnoDB หากคุณไม่สามารถรับคีย์ต่างประเทศใด ๆ ที่จะแสดงหลังจากเพิ่มพวกเขาอาจเป็นเพราะตารางของคุณใช้ MyISAM

เพื่อตรวจสอบ:

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

ในการแก้ไขให้ใช้สิ่งนี้:

ALTER TABLE `<yourtable>` ENGINE=InnoDB;

8
ข้อความค้นหาเหล่านั้นทำงานได้เร็วขึ้นมาก (จาก 2 วินาทีถึง 0.0015 วินาที) หากคุณระบุ k.TABLE_SCHEMA = DATABASE () และ k.TABLE_NAME = '<table>' ในส่วนคำสั่ง WHERE ตามที่ระบุไว้ที่นี่dev.mysql.com/doc/refman /5.5/th/…
guigouz

2
คำตอบที่ดี คุณมีทางออกสำหรับ MyISAM หรือไม่?
Beau Bouchard

2
MyISAM ไม่รองรับคีย์ต่างประเทศโชคไม่ดี dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
Andy

24

เป็นทางเลือกแทนคำตอบของ Node ถ้าคุณใช้ InnoDB และ FK ที่กำหนดไว้คุณสามารถสืบค้นฐานข้อมูล information_schema เช่น:

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

สำหรับคีย์ต่างประเทศจาก <table> หรือ

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

สำหรับ foreign key ไปที่ <table>

คุณสามารถรับ UPDATE_RULE และ DELETE_RULE ได้หากต้องการ


2
ฉันชอบคำตอบนี้เป็นการส่วนตัวเนื่องจากการใช้ตาราง REFERENTIAL_CONSTRAINTS จะให้กฎการอัปเดตและเรียงซ้อนของคุณ +1
Luke Madhanga

การค้นพบเกี่ยวกับโต๊ะคุณไม่ควรลืมว่ากุญแจต่างประเทศสามารถสร้างได้ทั้งสองแบบ!
Encoder

11

โซลูชันนี้จะไม่เพียงแสดงความสัมพันธ์ทั้งหมด แต่ยังรวมถึงชื่อข้อ จำกัด ซึ่งจำเป็นในบางกรณี (เช่นข้อ จำกัด การวาง):

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;

ถ้าคุณต้องการตรวจสอบตารางในฐานข้อมูลเฉพาะตอนท้ายของคิวรีให้เพิ่มชื่อสกีมา:

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

ในทำนองเดียวกันสำหรับชื่อคอลัมน์ที่ระบุให้เพิ่ม

และ table_name = 'table_name

ที่ท้ายแบบสอบถาม

แรงบันดาลใจจากโพสต์นี้ที่นี่


7

การใช้ REFERENCED_TABLE_NAME อาจไม่ทำงานและอาจเป็นค่า NULL เสมอ แบบสอบถามต่อไปนี้สามารถทำงานได้แทน:

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

4

วิธีที่รวดเร็วในการแสดงรายการ FK ของคุณ (การอ้างอิงคีย์ต่างประเทศ) โดยใช้

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;

แบบสอบถามนี้จะถือว่าข้อ จำกัด และตารางอ้างอิงและตารางอ้างอิงทั้งหมดอยู่ในสคีมาเดียวกัน

เพิ่มความคิดเห็นของคุณเอง

ที่มา: คู่มือ mysql อย่างเป็นทางการ


3

วิธีการแก้ปัญหาที่ฉันพบคือเปราะบาง มันขึ้นอยู่กับแบบแผนการตั้งชื่อของ django สำหรับกุญแจต่างประเทศ

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

จากนั้นในเปลือก

grep 'refs_tablename_id' mysql_output

2

หากต้องการค้นหาตารางทั้งหมดที่มีรหัสต่างประเทศเฉพาะเช่นemployee_id

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

2

หากคุณต้องการรับชื่อคอลัมน์ต่างประเทศด้วย:

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;

ขอบคุณทางออกที่ยอดเยี่ยม! ฉันต้องการชื่อคอลัมน์ด้วยเพื่อเพิ่ม: 'k.COLUMN_NAME'
Andreas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.