2

必要な関係があまりない古いデータベースのクリーンアップに役立つクエリを探しています。完璧である必要はありません。クリーンアップを開始し、データの整合性を確保するためのガイドとして役立ちます。

すべてのテーブルに適切な主キーがあり、まだ関連付けられていないテーブルの列に同じ名前があると想定しています。

理論的に言えば、複合キーを持つ 3 つのテーブルを持つことができます (このようにデータベースを設計することは選択しませんが、データベースのクリーンアップには制限があり、これらのタイプの複合/主キー/外部キーは一般的です):

Case.CaseId (PK)
Workstep.WorkstepId (PK)
Workstep.CaseId (PK,FK)
WorkQueue.CaseId (Case.CaseId とは関係ありませんが、関係があるはずです)

私ができるようにしたいのは、クエリを実行して、テーブル名、列名、関連していないがテーブルの外部キーのようなものを与える結果を出すことです。

テーブル名、列名は、主キー
WorkQueue、CaseId、Case.CaseId に関連している必要があります

以下で使用しているSQLを参照してください。ただし、主キーであると同時に外部キーの一部でもある主キーを返します。私の例と以下の SQL を再度使用すると、1 行を返す代わりに 2 行が返されます。

テーブル名、列名は、プライマリ キー
WorkQueue、CaseId、Workstep.CaseId に関連付ける必要があります (「実際の」プライマリ キー Case.CaseId にも関連付けられているため、この行は必要ありません)
WorkQueue、CaseId、Case.ケースID

    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
4

1 に答える 1

1

これは世界で最も美しいものではないかもしれませんが、かなりうまく機能します:

    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
于 2012-07-26T14:05:02.840 に答える