从数据库表中检索主键,标识列和特定名称列

时间:2017-06-20 14:12:54

标签: sql sql-server

我需要从所选数据库中的每个表中获取主键(如果存在),标识(如果存在)和名为“ID”(如果存在)的列。我有SQL查询来完成工作,但查询返回主键有时同时具有“否”和“是”值的记录。因此,导致多行数据,因此我使用单词DISTINCT来删除重复项。我假设这是由于在某些列上定义了索引。

怎么可能解决这个问题?

使用的SQL查询:

SELECT DISTINCT
    object_name(i.object_id) [Table], 
    c.name [Column], 
    IIF(i.is_primary_key = 1, 'Yes', 'No') [PK], 
    IIF(c.is_identity = 1, 'Yes', 'No') [Identity],
    IIF(UPPER(c.name) = 'ID', 'Yes', 'No') [Named ID]
FROM sys.indexes i
    INNER JOIN sys.columns c ON c.object_id = i.object_id
    INNER JOIN sys.identity_columns idc ON idc.object_id = c.object_id AND idc.column_id = c.column_id
WHERE 
    i.is_primary_key = 1 OR c.is_identity = 1 OR c.name = 'ID'
ORDER BY [Table];

3 个答案:

答案 0 :(得分:0)

您正在使用sys.indexes。一个表可以有多个索引,一个列可以使用多个索引。您的查询告诉您的是该列用于PK索引以及另一个索引(不是PK索引)。

此外,您的查询将排除所有不在索引中的列。

从sys.columns开始,改为使用外连接。对象id是表的id,而不是列的id,因此您还需要index_columns。

SELECT DISTINCT
    object_name(c.object_id) [Table], 
    c.name [Column], 
    i.is_primary_key,
    case i.is_primary_key when 1 then 'Yes' else 'No'end [PK], 
    case c.is_identity when 1 then 'Yes' else 'No'end [Identity],
    case c.name when 'ID' then 'Yes' else 'No'end [Named ID]
FROM sys.columns c
    left join sys.index_columns ic on  c.column_id = ic.column_id and c.object_id = ic.object_id
    left JOIN sys.indexes i ON i.index_id = ic.index_id and c.object_id = i.object_id  and i.is_primary_key= 1
    left JOIN sys.identity_columns idc ON idc.object_id = c.object_id AND idc.column_id = c.column_id
WHERE i.is_primary_key = 1 OR c.is_identity = 1 OR c.name = 'ID'
ORDER BY [Table];

答案 1 :(得分:0)

对于将来需要类似内容的人,我采用了Peter的答案(包括Sean Lange使用sys.tables的建议):

SELECT 
    t.name AS [Table], 
    c.name AS [Column], 
    CASE i.is_primary_key WHEN 1 THEN 'Yes' ELSE 'No' END [PK], 
    CASE idc.is_identity WHEN 1 THEN 'Yes' ELSE 'No' END [Identity],
    CASE c.name WHEN 'ID' THEN 'Yes' ELSE 'No' END [Named ID]
FROM 
    sys.tables t 
    LEFT JOIN sys.columns c ON c.object_id = t.object_id
    LEFT JOIN sys.identity_columns idc ON idc.object_id = t.object_id AND idc.column_id = c.column_id AND idc.is_identity = 1
    LEFT JOIN sys.index_columns ic ON ic.object_id = t.object_id AND ic.column_id = c.column_id
    LEFT JOIN sys.indexes i ON i.object_id = t.object_id AND i.index_id = ic.index_id AND i.is_primary_key = 1
WHERE t.type = 'U' AND (idc.is_identity = 1 OR i.is_primary_key = 1 OR c.name = 'ID')
ORDER BY t.name, c.name;

答案 2 :(得分:0)

您可以执行以下查询,但是您可以获得多列形成主键的结果,如下所示:

Multiple columns form the primary key

因为像:

ALTER TABLE [derived].[LocationParameterMedium] 
ADD CONSTRAINT [PK_LocationParameterMedium] PRIMARY KEY CLUSTERED ([CycleID] ASC, [LocationID] ASC, [ParameterID] ASC, [MediumID] ASC)
GO

可以通过将列卷起到单个列following link explains how to roll-up columns into a single column

来修复

查询:

SELECT 
    OBJECT_SCHEMA_NAME(t.object_id) AS [Schema], -- Incase there is mulple schemas and same table name
    t.name AS [Table], 
    c.name AS [Column], 
    IIF((SELECT 1 
        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE keyCU
        WHERE keyCU.COLUMN_NAME = c.name 
            AND keyCU.TABLE_SCHEMA = OBJECT_SCHEMA_NAME(t.object_id)
            AND keyCU.TABLE_NAME = t.name
            AND OBJECTPROPERTY(OBJECT_ID(keyCU.CONSTRAINT_SCHEMA + '.' + QUOTENAME(keyCU.CONSTRAINT_NAME)), 'IsPrimaryKey') = 1) = 1, 'Yes', 'No') [PK], 
    IIF(c.is_identity = 1, 'Yes', 'No') [Identity],
    IIF(c.name = 'ID', 'Yes', 'No') [Named ID]
FROM sys.tables AS t
LEFT JOIN sys.columns AS c
    ON t.object_id = c.object_id
    AND (c.is_identity = 1
        OR c.name = 'ID' 
        OR EXISTS ( SELECT 1 
                    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE keyCU
                    WHERE keyCU.COLUMN_NAME = c.name 
                        AND keyCU.TABLE_SCHEMA = OBJECT_SCHEMA_NAME(t.object_id)
                        AND keyCU.TABLE_NAME = t.name
                        AND OBJECTPROPERTY(OBJECT_ID(keyCU.CONSTRAINT_SCHEMA + '.' + QUOTENAME(keyCU.CONSTRAINT_NAME)), 'IsPrimaryKey') = 1
                  )
    )
---- To exclude tables where there is no PK, identity, or column name = 'ID' 
--WHERE c.name IS NOT NULL