2012-03-08 7 views
2

私はテーブルAnimalを持っています。データベース内の他の場所で外部キーが参照されているかどうかを調べるクエリ

私はこのテーブルからレコードをすべて外部キーとして参照するかどうかを示す1つの列からすべてを返したいとします。

はすなわち:

Animal_Id Name 
    1  Cat 
    2  Dog 
    3  Parrot 

私はこの戻りたい:特定Animal_Idを外部キーとしてデータベース内の他のテーブルで参照された場合、私が意味する「参照」で

AnimalId Name  Referenced 
    1  Cat   true 
    2  Dog   false 
    3  Parrot  true 

を。私が最初にINFORMATION_SCHEMAを照会し、テーブルは、この外部キーが含まれているものを見つけると、その後
select count(*) from eachTable where AnimalID = 1

誰もがそれを行う方法についてのスニペットを持っていますが、実行するループと動的SQLを使用することができると思いますか?

答えて

11

これはそれを行う必要があります。

SELECT OO.Animal_ID, OO.Name, CASE WHEN XX.REFERENCED IS NULL THEN 'false' ELSE 'true' END Referenced 
FROM Animal OO 
     OUTER APPLY (SELECT SUM(1) REFERENCED 
        FROM (SELECT FkAnimal_ID FROM AnimalRef1 RR WHERE RR.FkAnimal_ID = OO.Animal_ID UNION ALL 
          SELECT FkAnimal_ID FROM AnimalRef2 RR WHERE RR.FkAnimal_ID = OO.Animal_ID UNION ALL 
          SELECT FkAnimal_ID FROM AnimalRef3 RR WHERE RR.FkAnimal_ID = OO.Animal_ID) II) XX 

を使用すると、すべてのFKテーブルがわからない場合、あなたはどのあなたはできる、ALLクエリテーブルにUNIONのそのコレクションを生成するために、システムのメタデータテーブルを使用することができますその後、あなたのクエリに&ペーストをコピーします。再帰CTEを使用して単一のクエリで

WITH AKT AS (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 
       WHERE f.referenced_object_id = object_id('Animal')) 
SELECT 'SELECT ' + ColumnName + ' FROM ' + TableName + ' WHERE RR.' + ColumnName + ' = OO.' + ReferenceColumnName + ' UNION ALL' 
FROM AKT 

そして全体のことのために:

DECLARE @QUERY NVARCHAR(MAX) 

WITH AKT AS (SELECT ROW_NUMBER() OVER (ORDER BY f.name) RN, f.name AS ForeignKey 
        ,OBJECT_NAME(f.parent_object_id) AS TableName 
        ,COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName 
        ,SCHEMA_NAME(oo.schema_id) SchemaName 
        ,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 
        INNER JOIN sys.objects oo ON oo.object_id = fc.referenced_object_id 
       WHERE f.referenced_object_id = object_id('Animal')) 

    ,bs AS (SELECT AKT.RN 
        ,'SELECT ' + ColumnName + ' FROM ' + SchemaName + '.' + TableName + ' WHERE ' + ColumnName + ' = OO.' + ReferenceColumnName SubQuery 
      FROM AKT) 
    ,re AS (SELECT bs.RN, CAST(RTRIM(bs.SubQuery) AS VARCHAR(MAX)) Joined 
      FROM bs 
      WHERE bs.RN = 1 
      UNION ALL 
      SELECT bs2.RN, CAST(re.Joined + ' UNION ALL ' + ISNULL(RTRIM(bs2.SubQuery), '') AS VARCHAR(MAX)) Joined 
      FROM re, bs bs2 
      WHERE re.RN = bs2.RN - 1) 
    ,fi AS (SELECT ROW_NUMBER() OVER (ORDER BY RN DESC) RNK, Joined 
      FROM re) 
SELECT @QUERY = 'SELECT OO.Animal_ID, OO.Name, CASE WHEN XX.REFERENCED IS NULL THEN ''No'' ELSE ''Yes'' END Referenced 
FROM Animal OO 
     OUTER APPLY (SELECT SUM(1) REFERENCED 
        FROM (' + Joined + ') II) XX' 
FROM fi 
WHERE RNK = 1 

EXEC (@QUERY) 
+0

+1 2番目のソリューションでクエリアセンブリを実行すると、完全な解決策が得られる –

+0

あなたのチャレンジが受け入れられ、回答されました。 – Griffin

+0

OMG。これは素晴らしいです。先生ありがとう! – user194076