2010-10-11 6 views
28

В SQL Server, как получить ссылочную таблицу + имя столбца из внешнего ключа?SQL Server: Как получить ссылку на внешний ключ от information_schema?

Примечание: не таблица/столбец, в котором находится ключ, а ключ, на который он ссылается.

Пример:

Когда ключ [FA_MDT_ID] в таблице [T_ALV_Ref_FilterDisplay]. относится к [T_AP_Ref_Customer].[MDT_ID]

, например, при создании ограничения, как это:

ALTER TABLE [dbo].[T_ALV_Ref_FilterDisplay] WITH CHECK ADD CONSTRAINT [FK_T_ALV_Ref_FilterDisplay_T_AP_Ref_Customer] FOREIGN KEY([FA_MDT_ID]) 
REFERENCES [dbo].[T_AP_Ref_Customer] ([MDT_ID]) 
GO 

Мне нужно получить [T_AP_Ref_Customer].[MDT_ID] когда дано [T_ALV_Ref_FilterAnzeige].[FA_MDT_ID] в качестве входных данных

ответ

63

Ничего, это правильный ответ:
http://msdn.microsoft.com/en-us/library/aa175805(SQL.80).aspx

SELECT 
    KCU1.CONSTRAINT_NAME AS FK_CONSTRAINT_NAME 
    ,KCU1.TABLE_NAME AS FK_TABLE_NAME 
    ,KCU1.COLUMN_NAME AS FK_COLUMN_NAME 
    ,KCU1.ORDINAL_POSITION AS FK_ORDINAL_POSITION 
    ,KCU2.CONSTRAINT_NAME AS REFERENCED_CONSTRAINT_NAME 
    ,KCU2.TABLE_NAME AS REFERENCED_TABLE_NAME 
    ,KCU2.COLUMN_NAME AS REFERENCED_COLUMN_NAME 
    ,KCU2.ORDINAL_POSITION AS REFERENCED_ORDINAL_POSITION 
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC 

INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU1 
    ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG 
    AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA 
    AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME 

INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU2 
    ON KCU2.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG 
    AND KCU2.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA 
    AND KCU2.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME 
    AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION 
+3

Внимание! - Это не возвращает fks, которые ссылаются на уникальные столбцы индекса. См. Http://stackoverflow.com/questions/2895219/can-we-have-a-foreign-key-which-is-not-a-primary-key-in-any-other-table. –

+2

@Seth Reno: Это правильно в Microsoft SQL Server, потому что там вы можете ссылаться на уникальный индекс во внешнем ключе. Но SQL-стандарт не позволяет этого, и это не поддерживается всеми другими СУБД. Кроме того, в information_schema нет информации об индексе, поэтому нет возможности исправить это. Я бы сказал, если вы не ссылаетесь на первичный ключ как на внешний ключ, вы делаете что-то неправильно схематично. –

+0

Этот запрос почти корректно работает для меня. Мне пришлось добавить 'AND KCU2.TABLE_NAME = RC.REFERENCED_TABLE_NAME' в предложение ON для KCU2 JOIN, чтобы исключить неверные записи из-за большого количества таблиц в моей базе данных с первичным ключом с именем' PRIMARY'. Я запускаю MariaDB 5.5, но я подозреваю, что у другой СУБД будет аналогичная проблема. – JSmitty

13

Если вы можете жить с помощью сервера конкретной схемы SQL в каталоге, этот запрос вернет вам то, что вы ищете:

SELECT 
    fk.name, 
    OBJECT_NAME(fk.parent_object_id) 'Parent table', 
    c1.name 'Parent column', 
    OBJECT_NAME(fk.referenced_object_id) 'Referenced table', 
    c2.name 'Referenced column' 
FROM 
    sys.foreign_keys fk 
INNER JOIN 
    sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id 
INNER JOIN 
    sys.columns c1 ON fkc.parent_column_id = c1.column_id AND fkc.parent_object_id = c1.object_id 
INNER JOIN 
    sys.columns c2 ON fkc.referenced_column_id = c2.column_id AND fkc.referenced_object_id = c2.object_id 

Не знаете, как - если вообще - вы можете получить ту же информацию от взглядов INFORMATION_SCHEMA ....

+0

37'874 внешних ключей в моей базе данных около 100 таблиц? Я не уверен, но я не думаю, что это правильно. Я получаю 349, что, я думаю, более вероятно ... –

+2

@Quandary: извините, пропустил несколько условий ON - теперь это будет лучше (работает для меня, во всяком случае) –

+0

Как подключиться к этому с помощью INFORMATION_SCHEMA.KEY_COLUMN_USAGE, чтобы получить ORDINAL_POSITION поля? –

0

Я хотел аа которая позволила бы мне найти все столбцы «Key» и «ID», имеющие/отсутствующие ограничения. Поэтому мне нужны все столбцы по сравнению со списком всех PK OR FK ИЛИ Null, вот мой запрос. Надеюсь, это поможет кому-то еще!

SELECT 
    c.table_schema 
    ,c.table_name 
    ,c.column_name 
    ,KeyConstraints.constraint_type 
    ,KeyConstraints.constraint_schema 
    ,KeyConstraints.constraint_name 
    ,KeyConstraints.referenced_table_schema 
    ,KeyConstraints.referenced_table_name 
    ,KeyConstraints.referenced_column_name 
    ,KeyConstraints.update_rule 
    ,KeyConstraints.delete_rule 
FROM information_schema.columns AS c 
LEFT JOIN 
    (
     SELECT 
      FK.table_schema AS TABLE_SCHEMA 
      ,FK.table_name 
      ,CU.column_name 
      ,FK.constraint_type 
      ,c.constraint_schema 
      ,C.constraint_name 
      ,PK.table_schema AS REFERENCED_TABLE_SCHEMA 
      ,PK.table_name AS REFERENCED_TABLE_NAME 
      ,CCU.column_name AS REFERENCED_COLUMN_NAME 
      ,C.update_rule 
      ,C.delete_rule 
     FROM information_schema.referential_constraints AS C 

     INNER JOIN information_schema.table_constraints AS FK 
      ON C.constraint_name = FK.constraint_name 

     INNER JOIN information_schema.table_constraints AS PK 
      ON C.unique_constraint_name = PK.constraint_name 

     INNER JOIN information_schema.key_column_usage AS CU 
      ON C.constraint_name = CU.constraint_name 

     INNER JOIN information_schema.constraint_column_usage AS CCU 
      ON PK.constraint_name = CCU.constraint_name 

     WHERE (FK.constraint_type = 'FOREIGN KEY') 

     UNION 

     SELECT 
      ccu.table_schema 
      ,ccu.table_name 
      ,ccu.column_name 
      ,tc.constraint_type 
      ,ccu.constraint_schema 
      ,ccu.constraint_name 
      ,NULL 
      ,NULL 
      ,NULL 
      ,NULL 
      ,NULL 
     FROM information_schema.constraint_column_usage ccu 

     INNER JOIN information_schema.table_constraints tc 
      ON ccu.table_schema = tc.table_schema 
      AND ccu.table_name = tc.table_name 

     WHERE tc.constraint_type = 'PRIMARY KEY' 

    ) AS KeyConstraints 
    ON c.table_schema = KeyConstraints.table_schema 
    AND c.table_name = KeyConstraints.table_name 
    AND c.column_name = KeyConstraints.column_name 

WHERE c.column_name LIKE '%ID' OR c.column_name LIKE '%Key' 
ORDER BY c.table_schema 
     ,c.table_name 
     ,c.column_name 
; 

форматирования любезность: http://www.dpriver.com/pp/sqlformat.htm

+0

Пожалуйста, уделите время, чтобы переключиться на правильные параметры при использовании sqlformat. Ваша версия была совершенно нечитаема. Исправлено. Кроме того, используйте AS при объявлении псевдонима. Это поможет вам избежать множества потенциальных проблем. Формат SqlFormat будет отформатирован для вас, но он не задумывается о вас. –

+0

@StefanSteiger благодарит за отзыв. Я часто не размещал длинные запросы на SO, поэтому не был уверен в лучших вариантах использования. я буду помнить об этом в следующий раз. Я также попытаюсь не забыть включить классификатор «AS», это плохая привычка, я постоянно работаю над улучшением! – Justin

Смежные вопросы