Получение всех ключей таблицы с типами - PullRequest
0 голосов
/ 01 ноября 2011

Мне удалось собрать воедино этот запрос из различных примеров, чтобы получить все ключи таблицы:

select tbl.name,idx.name as indexname,t1.*,col.name as colname
from dbo.sysindexkeys as t1
LEFT JOIN dbo.sysindexes as idx on (t1.id=idx.id and t1.indid=idx.indid)
LEFT JOIN dbo.syscolumns as col on (col.id=t1.id and col.colid=t1.colid)
LEFT JOIN dbo.sysobjects as tbl on (idx.id=tbl.id)
ORDER BY tbl.name,idx.name,t1.keyno

Единственное, что мне нужно, это тип ключей, который, как я понимаю, должен быть PK, UQ или D (на данный момент не касается внешних ключей). Похоже, мне нужно снова присоединиться к sysobjects, чтобы получить столбец xtype, но я не могу найти правильный способ объединения.

На основании этого ответа Я пытался

select tbl.name,idx.name as indexname,s2.xtype,t1.*,col.name as colname
from dbo.sysindexkeys as t1
LEFT JOIN dbo.sysindexes as idx on (t1.id=idx.id and t1.indid=idx.indid)
JOIN sysobjects s2 on s2.parent_obj = t1.id
LEFT JOIN dbo.syscolumns as col on (col.id=t1.id and col.colid=t1.colid)
LEFT JOIN dbo.sysobjects as tbl on (idx.id=tbl.id)
ORDER BY tbl.name,idx.name,t1.keyno

но это приводит к нескольким записям на столбец индекса и с разными типами xty. Я хочу одну строку на столбец индекса (если индекс на три столбца, то должно быть три строки) все с правильным типом xtype. Что мне нужно изменить?

Ответы [ 2 ]

1 голос
/ 10 ноября 2011

Я вошел в ваш исходный оператор sql и получил его для возврата xtype для индекса из таблицы sysobjects:

select tbl.name,idx.name as indexname,t1.*,col.name as colname, tbl2.xtype
from dbo.sysindexkeys as t1
LEFT JOIN dbo.sysindexes as idx on (t1.id=idx.id and t1.indid=idx.indid)
LEFT JOIN dbo.syscolumns as col on (col.id=t1.id and col.colid=t1.colid)
LEFT JOIN dbo.sysobjects as tbl on (idx.id=tbl.id)
JOIN dbo.sysobjects AS tbl2 ON (idx.id = tbl2.parent_obj) AND (idx.name = tbl2.name)
ORDER BY tbl.name,idx.name,t1.keyno

idx.id - это идентификатор таблицы индексаотносится к.В таблице sysobjects нет ничего, кроме поля имени, совпадающего с тем, что находится в таблице sysindexes, поэтому к нему тоже нужно было присоединиться.Почти сделал еще одно левое соединение, но когда я это сделал, я получил строки из индексной таблицы для объектов статистики, которые не перечислены в таблице sysobjects.

РЕДАКТИРОВАТЬ: я вернулся и посмотрел, что потребуется, чтобыполучить информацию, которую вы ищете, и придумал следующую инструкцию SQL:

SELECT name, indexname, id, indid, colid, keyno, colname, 
    ISNULL(xtype, CASE WHEN is_index = 1 THEN 'IX' WHEN status&2 <> 0 THEN 'UQ' ELSE xtype END) as xtype
FROM 
(select TOP 100 PERCENT
    tbl.name,
    idx.name as indexname,
    t1.*,
    col.name as colname, 
    idx.status, 
    CAST(CASE WHEN (idx.status=0 OR idx.status&5<>0) THEN 1 ELSE 0 END AS bit) AS is_index,
    CAST(CASE WHEN idx.status&64<>0 THEN 1 ELSE 0 END AS bit) AS is_statistic,
    tbl2.xtype
from dbo.sysindexkeys as t1
LEFT JOIN dbo.sysindexes as idx on (t1.id=idx.id and t1.indid=idx.indid)
LEFT JOIN dbo.syscolumns as col on (col.id=t1.id and col.colid=t1.colid)
LEFT JOIN dbo.sysobjects as tbl on (idx.id=tbl.id)
LEFT JOIN dbo.sysobjects AS tbl2 ON (idx.id = tbl2.parent_obj) AND (idx.name = tbl2.name)
ORDER BY tbl.name,idx.name,t1.keyno) AS dts
WHERE is_statistic = 0

Я не уверен, как заставить отображаться типы 'D', поскольку их нет в таблице sysindexkeys..

1 голос
/ 09 ноября 2011

Вы можете попытаться использовать status из sysindexes для определения типа ключа.Запрос может быть следующим:

SELECT c.name AS [schema], a.name AS table_name, b.name AS key_name,
    CAST(CASE WHEN b.status&2048<>0 THEN 1 ELSE 0 END AS bit) AS is_PK_constraint,
    CAST(CASE WHEN b.status&4096<>0 THEN 1 ELSE 0 END AS bit) AS is_UNIQUE_constraint,
    CAST(CASE WHEN b.status&16<>0 THEN 1 ELSE 0 END AS bit) AS is_clustered,
    CAST(CASE WHEN b.status&2<>0 THEN 1 ELSE 0 END AS bit) AS is_unique_index,
    CAST(CASE WHEN b.status&64<>0 THEN 1 ELSE 0 END AS bit) AS is_allows_duplicate
FROM sysobjects a 
    INNER JOIN sysindexes b ON a.id = b.id 
    INNER JOIN sysusers c ON a.uid = c.uid 
WHERE b.status&0x800000=0 AND c.name<>'sys'
ORDER BY c.name, a.name, b.name

Я надеюсь, что это будет работать в ретро-версии SQL Server (SQL Server 2000), которую вы используете в настоящее время.

...