1

我正在尋找一個查詢來幫助清理舊數據庫,它沒有多少關係。我並不需要它是完美的,只是爲了幫助指導我開始清理並開始執行數據完整性。查詢查找可能的應該是外​​鍵的列?

我假設所有的表都具有正確的主鍵,並且尚未關聯的表中的列具有相同的名稱。

從理論上說,我可以有三個表,一個具有複合鍵(我也不會選擇來設計這樣的數據庫,但在它的清理很有限的,這些類型的複合/主/外鍵是常見的):

Case.CaseId(PK)
Workstep.WorkstepId(PK)
Workstep.CaseId(PK,FK)
WorkQueue.CaseId(不涉及Case.CaseId但應該是)

我希望能夠做的是運行一個查詢,並拿出結果,讓我索姆ething如表名,列名,那是沒有關係的,但應該是,該表的外鍵如:

表名,列名,應與PRIMARY KEY
工作隊列,CaseId,Case.CaseId

請參閱下面我正在使用的SQL,但它返回任何主鍵,即使是既是主鍵也是外鍵的一部分。使用而不是返回1行再次我的例子,下面的SQL,我得到2:

表名,列名,應與PRIMARY KEY
工作隊列,CaseId,Workstep.CaseId(我不希望這行,因爲它也涉及到「真正的」主鍵,Case.CaseId)
工作隊列,CaseId,Case.CaseId

SELECT 
    SubqueryAllPotentialForeignKeys.TABLE_NAME 
    ,SubqueryAllPotentialForeignKeys.COLUMN_NAME 
    ,(PrimaryKeys.TABLE_NAME + '.' + PrimaryKeys.COLUMN_NAME) as 'Possible Primary Key' 

--all potential foreign keys (column name matches another column name but there is no reference from this column anywhere else) 
FROM 
    ( 
    SELECT 
     INFORMATION_SCHEMA.COLUMNS.TABLE_NAME 
     ,INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME 
    FROM 
     INFORMATION_SCHEMA.COLUMNS 
    WHERE 
     --only get columns that are in multiple tables 
     INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME IN 
     (
      SELECT COLUMN_NAME FROM 
       (SELECT COLUMN_NAME, COUNT(COLUMN_NAME) AS ColNameCount FROM INFORMATION_SCHEMA.COLUMNS GROUP BY COLUMN_NAME) AS SubQueryColumns 
      WHERE ColNameCount > 1 
     ) 

     --only get the table.column if not part of a foreign or primary key 
     EXCEPT 
     (
      SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE 
     ) 

    ) AS SubqueryAllPotentialForeignKeys 

LEFT JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS PrimaryKeys ON 
    SubqueryAllPotentialForeignKeys.COLUMN_NAME = PrimaryKeys.COLUMN_NAME 

--when finding possible keys for our columns that don't have references, limit to primary keys 
WHERE 
    PrimaryKeys.CONSTRAINT_NAME LIKE '%PK_%' 

ORDER BY TABLE_NAME, COLUMN_NAME 

回答

0

這可能不是世界上最美麗的東西,但工作得很好織補:

SELECT * FROM 
(
    SELECT 
     SubqueryAllPotentialForeignKeys.TABLE_NAME 
     ,SubqueryAllPotentialForeignKeys.COLUMN_NAME 
     ,(PrimaryKeys.TABLE_NAME + '.' + PrimaryKeys.COLUMN_NAME) as 'Possible Primary Key' 

    --all potential foreign keys (column name matches another column name but there is no reference from this column anywhere else) 
    FROM 
     ( 
     SELECT 
      INFORMATION_SCHEMA.COLUMNS.TABLE_NAME 
      ,INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME 
     FROM 
      INFORMATION_SCHEMA.COLUMNS 
     WHERE 
      --only get columns that are in multiple tables 
      INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME IN 
      (
       SELECT COLUMN_NAME FROM 
        (SELECT COLUMN_NAME, COUNT(COLUMN_NAME) AS ColNameCount FROM INFORMATION_SCHEMA.COLUMNS GROUP BY COLUMN_NAME) AS SubQueryColumns 
       WHERE ColNameCount > 1 
      ) 

      --only get the table.column if not part of a foreign or primary key 
      EXCEPT 
      (
       SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE 
      ) 

     ) AS SubqueryAllPotentialForeignKeys 

    LEFT JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS PrimaryKeys ON 
     SubqueryAllPotentialForeignKeys.COLUMN_NAME = PrimaryKeys.COLUMN_NAME 

    --when finding possible keys for our columns that don't have references, limit to primary keys 
    WHERE 
     PrimaryKeys.CONSTRAINT_NAME LIKE '%PK_%' 
) AS Subquery 

--exclude all keys that are primary but also foreign 
WHERE [Possible Primary Key] NOT IN 
    (
     SELECT (TABLE_NAME + '.' + COLUMN_NAME) 
     FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
     WHERE CONSTRAINT_NAME LIKE 'FK_%' 
    ) 

ORDER BY TABLE_NAME, COLUMN_NAME