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