ฉันจะค้นหาการพึ่งพาคีย์ต่างประเทศทั้งหมดในคอลัมน์ใดคอลัมน์หนึ่งได้อย่างไร
อะไรคือทางเลือกที่แตกต่างกัน (กราฟิกใน SSMS, แบบสอบถาม / มุมมองใน SQL Server, เครื่องมือฐานข้อมูลบุคคลที่สาม, รหัสใน. NET)
ฉันจะค้นหาการพึ่งพาคีย์ต่างประเทศทั้งหมดในคอลัมน์ใดคอลัมน์หนึ่งได้อย่างไร
อะไรคือทางเลือกที่แตกต่างกัน (กราฟิกใน SSMS, แบบสอบถาม / มุมมองใน SQL Server, เครื่องมือฐานข้อมูลบุคคลที่สาม, รหัสใน. NET)
คำตอบ:
แบบสอบถามต่อไปนี้จะช่วยให้คุณเริ่มต้นได้ มันแสดงรายการความสัมพันธ์ของกุญแจต่างประเทศทั้งหมดในฐานข้อมูลปัจจุบัน
SELECT
FK_Table = FK.TABLE_NAME,
FK_Column = CU.COLUMN_NAME,
PK_Table = PK.TABLE_NAME,
PK_Column = PT.COLUMN_NAME,
Constraint_Name = C.CONSTRAINT_NAME
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK
ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK
ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
INNER JOIN (
SELECT
i1.TABLE_NAME,
i2.COLUMN_NAME
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2
ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
WHERE
i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
) PT
ON PT.TABLE_NAME = PK.TABLE_NAME
คุณยังสามารถดูความสัมพันธ์แบบกราฟิกภายในสตูดิโอการจัดการเซิร์ฟเวอร์ SQL ภายในไดอะแกรมฐานข้อมูล
ลอง: sp_help [table_name]
คุณจะได้รับข้อมูลทั้งหมดเกี่ยวกับโต๊ะรวมถึงกุญแจต่างประเทศทั้งหมด
sp_fkeys [table]
sp_fkeys @fktable_name='TableName'
หากคุณวางแผนที่จะลบหรือเปลี่ยนชื่อโต๊ะหรือคอลัมน์เพื่อค้นหาการอ้างอิงคีย์ต่างประเทศเท่านั้นอาจไม่เพียงพอ
ตารางอ้างอิงไม่ได้เชื่อมต่อกับ foreign key - คุณจะต้องค้นหาตารางอ้างอิงที่อาจไม่ได้เชื่อมต่อกับ foreign key (ฉันเคยเห็นฐานข้อมูลจำนวนมากที่มีการออกแบบไม่ดีที่ไม่ได้กำหนด foreign key แต่มีข้อมูลที่เกี่ยวข้อง ) วิธีแก้ไขอาจเป็นการค้นหาชื่อคอลัมน์ในตารางทั้งหมดและค้นหาคอลัมน์ที่คล้ายกัน
วัตถุฐานข้อมูลอื่น ๆ - นี่อาจเป็นเรื่องเล็กน้อย แต่ถ้าคุณกำลังมองหาการอ้างอิงทั้งหมดนอกจากนี้ยังเป็นสิ่งสำคัญในการตรวจสอบวัตถุที่ต้องพึ่งพา
เครื่องมือ GUI - ลองใช้ตัวเลือก SSMS“ ค้นหาวัตถุที่เกี่ยวข้อง” หรือเครื่องมือต่าง ๆ เช่นApexSQL Search (เครื่องมือฟรีรวมเข้ากับ SSMS) เพื่อระบุวัตถุที่ต้องพึ่งพาทั้งหมดรวมถึงตารางที่เชื่อมต่อกับ foreign key
เนื่องจากคำถามของคุณมุ่งเน้นไปที่ตารางเดียวคุณสามารถใช้สิ่งนี้:
EXEC sp_fkeys 'TableName'
ฉันพบมันดังนั้นที่นี่:
https://stackoverflow.com/a/12956348/652519
ฉันพบข้อมูลที่ฉันต้องการอย่างรวดเร็ว โดยจะแสดงรายการตารางคอลัมน์และชื่อของคีย์ต่างประเทศ
แก้ไข
นี่คือลิงค์ไปยังเอกสารประกอบที่ให้รายละเอียดพารามิเตอร์ต่าง ๆ ที่สามารถใช้ได้: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-fkeys-transact-sql
SELECT f.name AS ForeignKey, OBJECT_NAME(f.parent_object_id) AS TableName,
COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
หนึ่งที่ผมชอบที่จะใช้เรียกว่า SQL พึ่งพาการติดตามโดยเกตซอฟท์แวแดง คุณสามารถใส่วัตถุฐานข้อมูลใด ๆ เช่นตารางกระบวนงานที่เก็บไว้และจากนั้นมันจะวาดเส้นความสัมพันธ์ระหว่างวัตถุอื่น ๆ ทั้งหมดที่ขึ้นอยู่กับรายการที่คุณเลือก
ให้การแสดงกราฟิกที่ดีมากของการอ้างอิงในสคีมาของคุณ
ขอบคุณมากกับจอห์นสันสมคำค้นหาของเขายอดเยี่ยมมาก!
นอกจากนี้: คุณควรเพิ่ม "และ PT.ORDINAL_POSITION = CU.ORDINAL_POSITION" ที่ท้ายแบบสอบถามของคุณ
หากคุณมีหลายฟิลด์ในคีย์หลักคำสั่งนี้จะจับคู่ฟิลด์ที่สอดคล้องกัน (ฉันมีกรณีแบบสอบถามของคุณสร้างชุดค่าผสมทั้งหมดดังนั้นสำหรับ 2 ฟิลด์ในคีย์หลักฉันมีผลลัพธ์ 4 รายการสำหรับคีย์ต่างประเทศที่เกี่ยวข้อง) .
(ขออภัยฉันไม่สามารถแสดงความคิดเห็นคำตอบของ John ได้เนื่องจากฉันมีคะแนนชื่อเสียงไม่เพียงพอ)
แบบสอบถามนี้จะส่งกลับรายละเอียดเกี่ยวกับกุญแจต่างประเทศในตารางรองรับหลายคอลัมน์
SELECT *
FROM
(
SELECT
T1.constraint_name ConstraintName,
T2.COLUMN_NAME ColumnName,
T3.TABLE_NAME RefTableName,
T3.COLUMN_NAME RefColumnName,
T1.MATCH_OPTION MatchOption,
T1.UPDATE_RULE UpdateRule,
T1.DELETE_RULE DeleteRule
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS T1
INNER JOIN
INFORMATION_SCHEMA.KEY_COLUMN_USAGE T2
ON T1.CONSTRAINT_NAME = T2.CONSTRAINT_NAME
INNER JOIN
INFORMATION_SCHEMA.KEY_COLUMN_USAGE T3
ON T1.UNIQUE_CONSTRAINT_NAME = T3.CONSTRAINT_NAME
AND T2.ORDINAL_POSITION = T3.ORDINAL_POSITION) A
WHERE A.ConstraintName = 'table_name'
หลังจากค้นหามานานฉันพบวิธีแก้ปัญหาที่ใช้งานได้ ฐานข้อมูลของฉันไม่ใช้ sys.foreign_key_columns และ information_schema.key_column_usage มีคีย์หลักเท่านั้น
ฉันใช้ SQL Server 2015
การแก้ไข 1 (ไม่ค่อยได้ใช้)
หากวิธีการอื่นไม่ได้ผลก็จะทำงานได้ดี:
WITH CTE AS
(
SELECT
TAB.schema_id,
TAB.name,
COL.name AS COLNAME,
COl.is_identity
FROM
sys.tables TAB INNER JOIN sys.columns COL
ON TAB.object_id = COL.object_id
)
SELECT
DB_NAME() AS [Database],
SCHEMA_NAME(Child.schema_id) AS 'Schema',
Child.name AS 'ChildTable',
Child.COLNAME AS 'ChildColumn',
Parent.name AS 'ParentTable',
Parent.COLNAME AS 'ParentColumn'
FROM
cte Child INNER JOIN CTE Parent
ON
Child.COLNAME=Parent.COLNAME AND
Child.name<>Parent.name AND
Child.is_identity+1=Parent.is_identity
โซลูชัน 2 (ใช้กันทั่วไป)
ในกรณีส่วนใหญ่สิ่งนี้จะใช้ได้ดี:
SELECT
DB_NAME() AS [Database],
SCHEMA_NAME(fk.schema_id) AS 'Schema',
fk.name 'Name',
tp.name 'ParentTable',
cp.name 'ParentColumn',
cp.column_id,
tr.name 'ChildTable',
cr.name 'ChildColumn',
cr.column_id
FROM
sys.foreign_keys fk
INNER JOIN
sys.tables tp ON fk.parent_object_id = tp.object_id
INNER JOIN
sys.tables tr ON fk.referenced_object_id = tr.object_id
INNER JOIN
sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
INNER JOIN
sys.columns cp ON fkc.parent_column_id = cp.column_id AND fkc.parent_object_id = cp.object_id
INNER JOIN
sys.columns cr ON fkc.referenced_column_id = cr.column_id AND fkc.referenced_object_id = cr.object_id
WHERE
-- CONCAT(SCHEMA_NAME(fk.schema_id), '.', tp.name, '.', cp.name) LIKE '%my_table_name%' OR
-- CONCAT(SCHEMA_NAME(fk.schema_id), '.', tr.name, '.', cr.name) LIKE '%my_table_name%'
ORDER BY
tp.name, cp.column_id
คุณสามารถใช้ INFORMATION_SCHEMA.KEY_COLUMN_USAGE และ sys.foreign_key_columns เพื่อรับข้อมูลเมตาของคีย์ต่างประเทศสำหรับตารางเช่นชื่อข้อ จำกัด ตารางอ้างอิงและคอลัมน์อ้างอิงเป็นต้น
ด้านล่างคือแบบสอบถาม:
SELECT CONSTRAINT_NAME, COLUMN_NAME, ParentTableName, RefTableName,RefColName FROM
(SELECT CONSTRAINT_NAME,COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = '<tableName>') constraint_details
INNER JOIN
(SELECT ParentTableName, RefTableName,name ,COL_NAME(fc.referenced_object_id,fc.referenced_column_id) RefColName FROM (SELECT object_name(parent_object_id) ParentTableName,object_name(referenced_object_id) RefTableName,name,OBJECT_ID FROM sys.foreign_keys WHERE parent_object_id = object_id('<tableName>') ) f
INNER JOIN
sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id ) foreign_key_detail
on foreign_key_detail.name = constraint_details.CONSTRAINT_NAME
เพียงแค่ทราบคำตอบ @ @ John Sansom
หากค้นหาการพึ่งพาคีย์ต่างประเทศฉันคิดว่าประโยค PT ควรอยู่ที่:
i1.CONSTRAINT_TYPE = 'FOREIGN KEY' -- instead of 'PRIMARY KEY'
และเงื่อนไขON :
ON PT.TABLE_NAME = FK.TABLE_NAME – instead of PK.TABLE_NAME
ตามปกติแล้วจะใช้คีย์หลักของตารางต่างประเทศฉันคิดว่าปัญหานี้ไม่เคยถูกสังเกตมาก่อน
SELECT obj.name AS FK_NAME,
sch.name AS [schema_name],
tab1.name AS [table],
col1.name AS [column],
tab2.name AS [referenced_table],
col2.name AS [referenced_column]
FROM sys.foreign_key_columns fkc
INNER JOIN sys.objects obj
ON obj.object_id = fkc.constraint_object_id
INNER JOIN sys.tables tab1
ON tab1.object_id = fkc.parent_object_id
INNER JOIN sys.schemas sch
ON tab1.schema_id = sch.schema_id
INNER JOIN sys.columns col1
ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
INNER JOIN sys.tables tab2
ON tab2.object_id = fkc.referenced_object_id
INNER JOIN sys.columns col2
ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
มันจะทำให้คุณ:
FK นั้นเป็น Schema ที่ FK เป็นเจ้าของ
ใช้ข้อมูล information_chema;
SELECT COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM KEY_COLUMN_USAGE
WHERE (table_name = *tablename*) AND NOT (REFERENCED_TABLE_NAME IS NULL)