Foreign Key Index

  • Hi,

    How to check the foreign key column index created or not?

    Any one can give a idea about this.

    thanks

    Ram

  • When you create a foreign key, it's a constraint, not an index. If you want an index on a foreign key, that must be created separately.

    You can look at the system tables sys.foreign_keys and sys.foreign_keys_columns to see what's been created.

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

  • As Grant suggested these are two separate . However you can think for something to get a relation...

    Select A.name,OBJECT_NAME(A.parent_object_id),key_index_id,B.type_DESC From sys.foreign_keys a

    INNER JOIN sys.indexes b oN a.parent_object_id = b.object_id AND a.key_index_id = B.index_id

  • sqlzealot-81 (9/7/2011)


    As Grant suggested these are two separate . However you can think for something to get a relation...

    Select A.name,OBJECT_NAME(A.parent_object_id),key_index_id,B.type_DESC From sys.foreign_keys a

    INNER JOIN sys.indexes b oN a.parent_object_id = b.object_id AND a.key_index_id = B.index_id

    Err, no. The key_index_id column in sys.foreign_keys is the ID of the unique index in the referenced table, not the id of an index that may or may not have been created on the foreign key column in the referencing table.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • Ohhh Okei, I was not able to find a relation. Thanks for correcting me. My sincere apologies .I own my mistake.

  • You can determine what FK's do not have an index on the column with a query like this:

    SELECT

    OBJECT_NAME(IC.object_id, DB_ID()) AS table_name,

    FK.name AS fk_name,

    FK.type_desc,

    I.name AS index_name,

    I.type_desc,

    FK.create_date,

    FK.modify_date,

    FK.is_disabled,

    FK.is_not_for_replication,

    FK.is_not_trusted,

    FK.delete_referential_action,

    FK.delete_referential_action_desc,

    FK.update_referential_action,

    FK.update_referential_action_desc,

    IC.index_id,

    IC.index_column_id,

    IC.key_ordinal,

    I.is_unique,

    I.ignore_dup_key,

    I.is_primary_key,

    I.is_unique_constraint,

    I.fill_factor

    FROM

    sys.foreign_keys AS FK

    JOIN sys.foreign_key_columns AS FKC

    ON FK.object_id = FKC.constraint_object_id

    LEFT JOIN sys.index_columns AS IC

    JOIN sys.indexes AS I

    ON IC.index_id = I.index_id AND

    IC.object_id = I.object_id

    ON FKC.parent_object_id = IC.object_id AND

    FKC.parent_column_id = IC.column_id

    Keep in mind that that this does not consider if the column is the leading column in the index, so you can't say for sure if the index will be relevant to the FK.

  • here's my take on it;

    this query featuring a CTE lists all foreign keys, and if there is an index with the leading column on the child table or not.

    if it exists, you can see some of it in the data, otherwise it creates a PotentialIndex statement in a different column for output...i did take Jacks caveat into consideration about the leading column of an index being critical for the join., and i completely ignored multi column foreign keys as too much work without someone cutting a check fo rhte time to fiddle with it....

    for a practical applicaiton, i think i'd only add an index like this on tables with lots of rows in it, but

    a bit 'o' feedback would be appreciated.

    --select * from sys.index_columns

    WITH MyIndexes

    AS (SELECT

    DISTINCT

    idxz.name AS IndexName,

    idxz.object_id,

    OBJECT_NAME(idxz.object_id) AS TableName,

    ixcolnamez.name AS IndexColumnName

    FROM

    sys.indexes idxz

    INNER JOIN sys.index_columns idxcolz

    ON idxz.index_id = idxcolz.index_id

    INNER JOIN sys.columns ixcolnamez

    ON idxcolz.object_id = ixcolnamez.object_id

    AND idxz.object_id = ixcolnamez.object_id

    AND idxcolz.column_id = ixcolnamez.column_id

    WHERE

    index_column_id = 1 --because only the lead column will help for the join

    )

    SELECT

    SCHEMA_NAME(chldz.schema_id) AS SchemaName,

    objz.name AS FKName,

    parenz.name AS ParentTable,

    pcolz.name AS ParentColumn,

    chldz.name AS ChildTable,

    ccolz.name AS ChildColumn,

    MyIndexes.*,

    CASE

    WHEN MyIndexes.object_id IS NULL

    THEN 'CREATE INDEX [IX_FK_' + chldz.name + '_' + ccolz.name + '] ON ' + QUOTENAME(SCHEMA_NAME(chldz.schema_id)) + '.' + QUOTENAME(chldz.name) + '(' + QUOTENAME(ccolz.name) + ');'

    ELSE ''

    END AS PotentialIndex

    FROM

    sys.sysforeignkeys fkeyz

    INNER JOIN sys.objects objz

    ON fkeyz.constid = objz.object_id

    INNER JOIN sys.objects parenz

    ON fkeyz.rkeyid = parenz.object_id

    INNER JOIN sys.columns pcolz

    ON parenz.object_id = pcolz.object_id

    AND fkeyz.rkey = pcolz.column_id

    INNER JOIN sys.objects chldz

    ON fkeyz.fkeyid = chldz.object_id

    INNER JOIN sys.columns ccolz

    ON chldz.object_id = ccolz.object_id

    AND fkeyz.fkey = ccolz.column_id

    LEFT OUTER JOIN MyIndexes

    ON chldz.object_id = MyIndexes.object_id

    AND ccolz.name = MyIndexes.IndexColumnName

    Lowell


    --help us help you! If you post a question, make sure you include a CREATE TABLE... statement and INSERT INTO... statement into that table to give the volunteers here representative data. with your description of the problem, we can provide a tested, verifiable solution to your question! asking the question the right way gets you a tested answer the fastest way possible!

  • Lowell (9/13/2011)


    here's my take on it;

    this query featuring a CTE lists all foreign keys, and if there is an index with the leading column on the child table or not.

    if it exists, you can see some of it in the data, otherwise it creates a PotentialIndex statement in a different column for output...i did take Jacks caveat into consideration about the leading column of an index being critical for the join., and i completely ignored multi column foreign keys as too much work without someone cutting a check fo rhte time to fiddle with it....

    for a practical applicaiton, i think i'd only add an index like this on tables with lots of rows in it, but

    a bit 'o' feedback would be appreciated.

    --select * from sys.index_columns

    WITH MyIndexes

    AS (SELECT

    DISTINCT

    idxz.name AS IndexName,

    idxz.object_id,

    OBJECT_NAME(idxz.object_id) AS TableName,

    ixcolnamez.name AS IndexColumnName

    FROM

    sys.indexes idxz

    INNER JOIN sys.index_columns idxcolz

    ON idxz.index_id = idxcolz.index_id

    INNER JOIN sys.columns ixcolnamez

    ON idxcolz.object_id = ixcolnamez.object_id

    AND idxz.object_id = ixcolnamez.object_id

    AND idxcolz.column_id = ixcolnamez.column_id

    WHERE

    index_column_id = 1 --because only the lead column will help for the join

    )

    SELECT

    SCHEMA_NAME(chldz.schema_id) AS SchemaName,

    objz.name AS FKName,

    parenz.name AS ParentTable,

    pcolz.name AS ParentColumn,

    chldz.name AS ChildTable,

    ccolz.name AS ChildColumn,

    MyIndexes.*,

    CASE

    WHEN MyIndexes.object_id IS NULL

    THEN 'CREATE INDEX [IX_FK_' + chldz.name + '_' + ccolz.name + '] ON ' + QUOTENAME(SCHEMA_NAME(chldz.schema_id)) + '.' + QUOTENAME(chldz.name) + '(' + QUOTENAME(ccolz.name) + ');'

    ELSE ''

    END AS PotentialIndex

    FROM

    sys.sysforeignkeys fkeyz

    INNER JOIN sys.objects objz

    ON fkeyz.constid = objz.object_id

    INNER JOIN sys.objects parenz

    ON fkeyz.rkeyid = parenz.object_id

    INNER JOIN sys.columns pcolz

    ON parenz.object_id = pcolz.object_id

    AND fkeyz.rkey = pcolz.column_id

    INNER JOIN sys.objects chldz

    ON fkeyz.fkeyid = chldz.object_id

    INNER JOIN sys.columns ccolz

    ON chldz.object_id = ccolz.object_id

    AND fkeyz.fkey = ccolz.column_id

    LEFT OUTER JOIN MyIndexes

    ON chldz.object_id = MyIndexes.object_id

    AND ccolz.name = MyIndexes.IndexColumnName

    Nice work Lowell.

    Jason...AKA CirqueDeSQLeil
    _______________________________________________
    I have given a name to my pain...MCM SQL Server, MVP
    SQL RNNR
    Posting Performance Based Questions - Gail Shaw[/url]
    Learn Extended Events

Viewing 8 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic. Login to reply