2012-06-29 6 views
0

Je souhaite trouver toutes les clés étrangères dans une table et, pour chaque clé étrangère, trouver la colonne de clé primaire & pointant vers. Je dois le faire en utilisant INFORMATION_SCHEMA parce que nous voulons utiliser ceci contre tous les fournisseurs de DB (ou du moins tout ce qui implémente correctement INFORMATION_SCHEMA).Comment trouver les clés primaires pour toutes les clés étrangères dans une base de données à l'aide de INFORMATION_SCHEMA

Le meilleur que je suis venu avec est:

"SELECT k.COLUMN_NAME, ccu.TABLE_NAME AS 'references_table', ccu.COLUMN_NAME AS 'references_field' " + 
"FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS k LEFT OUTER JOIN " + 
"INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS c ON k.TABLE_NAME = c.TABLE_NAME AND k.TABLE_SCHEMA = c.TABLE_SCHEMA AND " + 
"k.TABLE_CATALOG = c.TABLE_CATALOG AND k.CONSTRAINT_CATALOG = c.CONSTRAINT_CATALOG AND " + 
"k.CONSTRAINT_NAME = c.CONSTRAINT_NAME LEFT OUTER JOIN " + 
"INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS rc ON rc.CONSTRAINT_SCHEMA = c.CONSTRAINT_SCHEMA AND " + 
"rc.CONSTRAINT_CATALOG = c.CONSTRAINT_CATALOG AND rc.CONSTRAINT_NAME = c.CONSTRAINT_NAME LEFT OUTER JOIN " + 
"INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS ccu ON rc.UNIQUE_CONSTRAINT_SCHEMA = ccu.CONSTRAINT_SCHEMA AND " + 
"rc.UNIQUE_CONSTRAINT_CATALOG = ccu.CONSTRAINT_CATALOG AND rc.UNIQUE_CONSTRAINT_NAME = ccu.CONSTRAINT_NAME " + 
"WHERE(k.CONSTRAINT_CATALOG = DB_NAME()) AND (k.TABLE_NAME = '" + table.Name + "') AND (c.CONSTRAINT_TYPE = 'FOREIGN KEY')"; 

Cela me semble trop compliqué. Y a-t-il un meilleur choix pour cela?

grâce - dave

+0

Savez-vous avant-vous que chaque relation pk/fk y est exécuté dans la base de données? – EastOfJupiter

+0

@TexasTubbs - peut-être pas. Mais nous pouvons utiliser ceux qui sont dans les métadonnées et habituellement c'est tout. –

Répondre

2
SELECT ccu1.TABLE_NAME as fkTable, ccu1.COLUMN_NAME as fkColumn, 
     ccu2.TABLE_NAME as referencedTable, ccu2.COLUMN_NAME as referencedColumn 
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu1, 
     INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu2, 
     INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc 
WHERE rc.CONSTRAINT_NAME = ccu1.CONSTRAINT_NAME 
AND  rc.UNIQUE_CONSTRAINT_NAME = ccu2.CONSTRAINT_NAME 

J'ai testé cette contre une base de données SQL Server 2008 et lorsqu'il est exécuté dans le contexte de ma base de données de l'utilisateur, il a renvoyé tous mes tables définies avec des clés étrangères, et la table liée et de la colonne.

Vous pouvez également filtrer ceci bien sûr.

+0

merci, cela fonctionne. Une correction cependant, il doit être ccu1.COLUMN_NAME comme fkColumn. C'est beaucoup plus simple et plus clair. Et très intelligent comment vous accédez à la même table de deux façons différentes. –

+0

Bonne prise Je pense que j'ai choisi le mauvais nom de colonne avec intellisense. Je l'ai édité. – Jim

+0

Maintenant, si seulement tous les fournisseurs SQL implémentaient complètement et correctement les tables INFORMATION_SCHEMA standard ... –

0

La réponse de Jim ne renvoie pas correctement toutes les clés étrangères si la table référencée (la table que la clé étrangère recherche) a une clé unique car elle utilise la colonne UNIQUE_CONSTRAINT_NAME. Je suggère d'utiliser:

SELECT 
    FK = fk.name, 
    FKTable = QUOTENAME(OBJECT_SCHEMA_NAME(fkcol.[object_id])) 
     + '.' + QUOTENAME(OBJECT_NAME(fkcol.[object_id])), 
    FKCol = fkcol.name, 
    ' references => ', 
    PKTable = QUOTENAME(OBJECT_SCHEMA_NAME(pkcol.[object_id])) 
     + '.' + QUOTENAME(OBJECT_NAME(pkcol.[object_id])), 
    PKCol = pkcol.name 
FROM sys.foreign_keys AS fk 
INNER JOIN sys.foreign_key_columns AS fkc 
ON fk.[object_id] = fkc.constraint_object_id 
INNER JOIN sys.columns AS fkcol 
ON fkc.parent_object_id = fkcol.[object_id] 
AND fkc.parent_column_id = fkcol.column_id 
INNER JOIN sys.columns AS pkcol 
ON fkc.referenced_object_id = pkcol.[object_id] 
AND fkc.referenced_column_id = pkcol.column_id 
ORDER BY fkc.constraint_column_id; 

Source: http://sqlblog.com/blogs/aaron_bertrand/archive/2011/11/03/the-case-against-information-schema-views.aspx

2

La réponse initialement acceptée ne prend pas correctement en compte une base de données à l'aide des clés primaires composites.

Essayez ceci:

select fku.CONSTRAINT_NAME, fku.ORDINAL_POSITION 
     , fku.TABLE_SCHEMA as FK_TABLE_SCHEMA 
     , fku.TABLE_NAME as FK_TABLE_NAME 
     , fku.COLUMN_NAME as FK_COLUMN_NAME 
     , pku.TABLE_SCHEMA as PK_TABLE_SCHEMA 
     , pku.TABLE_NAME as PK_TABLE_NAME 
     , pku.COLUMN_NAME as PK_COLUMN_NAME 

from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc 
     INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE pku 
      ON rc.UNIQUE_CONSTRAINT_NAME = pku.CONSTRAINT_NAME 
     INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE fku 
      ON rc.CONSTRAINT_NAME = fku.CONSTRAINT_NAME AND pku.ORDINAL_POSITION = fku.ORDINAL_POSITION 
order by fku.TABLE_SCHEMA, fku.TABLE_NAME, fku.ORDINAL_POSITION 
Questions connexes