查询以获取MsSQL表的唯一索引和主键

时间:2009-02-23 17:01:01

标签: sql-server indexing

SELECT sysobjects.xtype, syscolumns.name, sysindexkeys.indid, sysobjects.type
FROM
    syscolumns
LEFT JOIN sysobjects ON syscolumns.id = sysobjects.id
LEFT JOIN sysindexkeys ON (
     syscolumns.id = sysindexkeys.id AND syscolumns.colid = sysindexkeys.colid
)
WHERE sysobjects.name = '{$table}'
AND sysindexkeys.indid IS NOT NULL
ORDER BY sysindexkeys.indid, sysindexkeys.keyno

我实际上正在使用以下查询来检索列名和keyno。

问题是我的表有3个字段:

user_id
config_name
config_value

在user_id和config_name上使用主键。

我希望得到这个系列:

[
  ['name' => 'user_id', 'keyno' => 1],
  ['name' => 'config_name', 'keyno' => 1]
]

但我明白了:

[
  ['name' => 'user_id', 'keyno' => 1],
  ['name' => 'config_name', 'keyno' => 2]
]

我做错了什么?

修改 我使用两个索引表获得了相同的怪异结果

表:     project_image_id     PROJECT_ID     project_image_src

project_image_id上​​的PK和project_id上的唯一索引AND project_image_src

预期:

[
  ['name' => 'project_image_id', 'keyno' => 1],
  ['name' => 'project_id', 'keyno' => 2]
  ['name' => 'project_image_src', 'keyno' => 2]
]

但我明白了:

[
  ['name' => 'project_image_id', 'keyno' => 1],
  ['name' => 'project_id', 'keyno' => 1]
  ['name' => 'project_image_src', 'keyno' => 2]
]

6 个答案:

答案 0 :(得分:2)

对我来说这似乎是对的,你的索引有2列,user_id有位置1,config_name有位置2

来自BOL keyno:列在索引中的位置

为什么你认为他们都是1?

在这里,你需要加入回到sysobject表但是在索引而不是表本身

SELECT s2.xtype, syscolumns.name, sysindexkeys.indid, sysobjects.type
FROM
    syscolumns
LEFT JOIN sysobjects ON syscolumns.id = sysobjects.id
LEFT JOIN sysindexkeys ON (
     syscolumns.id = sysindexkeys.id AND syscolumns.colid = sysindexkeys.colid
)
join sysobjects s2 on s2.parent_obj = sysindexkeys.id
WHERE sysobjects.name = '{$table}'
and s2.type = 'K'
AND sysindexkeys.indid IS NOT NULL
ORDER BY sysindexkeys.indid, sysindexkeys.keyno

答案 1 :(得分:2)

有一些不错的主键解决方案,但他们并没有完全回答这个请求。还询问了如何确定列是否为唯一索引。

选项1:

要确定唯一索引,以下系统函数可以告诉您表“TableName”中特定索引“IndexName”的状态:

SELECT INDEXPROPERTY(OBJECT_ID('TableName'),'IndexName','IsUnique')

选项2:

然而,上述问题源于想知道COLUMN是否是唯一索引。这意味着您需要一个列表,列出所讨论的列是索引中唯一的列。因此,可以使用这样的组合:

-- Note: If a "1" appears in the select below, the index (and by extension, the column) is a unique index.


SELECT si.name, INDEXPROPERTY(x.TableID,si.name,'IsUnique') [IsUnique]
FROM sysindexes si
JOIN (SELECT OBJECT_ID('TableName') [TableID]) x  -- HERE IS YOUR TABLE NAME
  ON si.id = x.TableID
-- This restricts the selection to your column.
JOIN (
    SELECT id, indid 
    FROM sysindexkeys
    WHERE colid IN (
        -- For 2005 and up: SELECT COLUMNPROPERTY(OBJECT_ID('TableName'), 'ColumnName', 'ColumnId')
        SELECT colid
        FROM syscolumns
        WHERE name IN ('ColumnName')              -- HERE IS YOUR COLUMN NAME
    )
) y
  ON si.indid = y.indid
 AND x.TableID = y.id
WHERE si.status <> 0
  -- This eliminates occurrences of the column found in indexes with multiple columns.
  AND si.indid NOT IN (
    SELECT indid
    FROM sysindexkeys
    WHERE id = x.TableID
    GROUP BY indid
    HAVING COUNT(*) > 1
)

选项3:

使用index_name,index_description,index_keys创建一个表(IndexTable),并插入以下命令的结果:

sp_helpindex 'TableName'

然后,从这个结果中查询(或使用类似的查询):

SELECT *
FROM IndexTable
WHERE index_description LIKE '%unique%'
  AND index_keys = 'ColumnName'

希望这会有所帮助,或者如果您有更简洁的解决方案,请发帖。

答案 2 :(得分:1)

尝试此查询:

SELECT A.TABLE_NAME, A.CONSTRAINT_NAME, B.COLUMN_NAME
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS A, 
         INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE B
    WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND
          A.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND
          A.TABLE_NAME='{$tableName}'
    ORDER BY A.TABLE_NAME

{$tableName}替换为您的表名,您将获得特定表的所有主键,无论该表是具有单个主键还是多个主键。

答案 3 :(得分:1)

select sc.name 
  from sys.indexes si 
          join sys.tables st 
             on si.object_id = st.object_id
          join sys.index_columns sic 
             on sic.object_id = si.object_id and 
                sic.index_id = si.index_id
          join sys.columns sc 
             on sic.object_id = sc.object_id and 
                sic.column_id = sc.column_id
  where st.name = @table_name and 
        si.is_primary_key = 1
  order by sic.index_column_id 

答案 4 :(得分:0)

问题是你得到了“列在索引中的位置”。这样,它就不存在两个具有相同位置的列。

答案 5 :(得分:0)

SELECT sysobjects.name , syscolumns.name, systypes.name, syscolumns.length ,
       syscolumns.xprec , syscolumns.xscale ,

( 
SELECT 'PK'
  FROM syscolumns C
 WHERE C.name = syscolumns.name AND C.id IN (SELECT O.id
                  FROM sysobjects O
                 WHERE O.name = sysobjects.name)
   AND C.colid IN (SELECT SIK.colid 
                   FROM sysindexkeys SIK 
                   JOIN sysobjects SO ON SIK.id= SO.id  
                  WHERE SIK.indid = 1
                    AND SO.[name] = sysobjects.name)
)
FROM 
    sysobjects , syscolumns 
       , systypes  
    WHERE 
    sysobjects.xtype='U' 
    AND sysobjects.id = syscolumns.id AND syscolumns.xtype=systypes.xtype
    AND sysobjects.name LIKE ?
 ORDER BY sysobjects.name  , syscolumns.COLORDER