Elenco di indici e vincoli


10

Sto cercando un database SQL Server per un'applicazione che ho ereditato. Non ho esaminato SQL Server per circa 10 anni, quindi per favore abbi pazienza.

La tabella del database che sto guardando ha una bigint NOT NULLcolonna chiamata id, tuttavia, quando controllo i vincoli, non ne vedo nessuno, e lo stesso vale per tutte le tabelle del database.

Ho ragione nel supporre che non ci siano chiavi primarie e nessuna indicizzazione (in cluster o non cluster) su queste tabelle?

Ho eseguito le seguenti query e i risultati sembrano confermare il mio sospetto:

//**returns 0**
select count(*) from INFORMATION_SCHEMA.TABLE_CONSTRAINTS;

//**returns no rows**
select * from sys.indexes
where object_id = (select object_id from sys.objects where name = 'NAME-OF-TABLE');

//**returns all tables in database**
SELECT name
FROM sys.tables 
WHERE OBJECTPROPERTY(object_id,'IsIndexed') = 0;

Risposte:


9

Queste due domande potrebbero esserti utili. Il primo elencherà tutte le tabelle e gli indici su quelle tabelle nel database. Se la tabella non appare nell'elenco non ha alcun indice definito su di essa. Queste query presuppongono SQL Server versione 2005 o successive.

SELECT 
    IndexName = QUOTENAME(I.name), 
    TableName =
        QUOTENAME(SCHEMA_NAME(T.[schema_id])) + 
        N'.' + QUOTENAME(T.name), 
    IsPrimaryKey = I.is_primary_key
FROM sys.indexes AS I
INNER JOIN sys.tables AS T
    ON I.[object_id] = T.[object_id]
WHERE
    I.type_desc <> N'HEAP'
ORDER BY 
    TableName ASC, 
    IndexName ASC;

La seconda query riporterà per ogni tabella la colonna identità, se presente su ciascuna tabella del database.

SELECT
    TableName =
        QUOTENAME(SCHEMA_NAME(T.[schema_id])) + 
        N'.' + QUOTENAME(T.name), 
    IdentityColumn = COALESCE(QUOTENAME(C.name), N'No identity column')
FROM sys.tables AS T
LEFT OUTER JOIN sys.columns AS C
    ON T.[object_id] = C.[object_id]
    AND C.is_identity = 1
ORDER BY
    TableName ASC;

Per limitare le query a una tabella specifica aggiungere una WHEREclausola simile a:

WHERE T.name = N'NAME-OF-TABLE'

2

No, qualcosa non è corretto.

Il controllo sys.indexesdovrebbe restituire una riga anche se la tabella non ha indici. L'heap ha ancora un record sys.indexescon a type_descdi 'HEAP' e typedi 0.

Penso che probabilmente dovrai assicurarti di essere nel giusto contesto di database OBJECT_ID()e che sys.objectssono specifici del database.

Prova questo:

USE MyDatabase

SELECT *
FROM sys.indexes
WHERE object_id = OBJECT_ID('schema.MyTableName')

1

Non sono sicuro che tu sia interessato a tutti i vincoli, ma INFORMATION_SCHEMA.TABLE_CONSTRAINTS non sembra restituire i vincoli DEFAULT - TABLE_CONSTRAINTS (Transact-SQL)

CHECK, UNICO, CHIAVE PRIMARIA, CHIAVE ESTERA

Questa query farà un semplice conteggio rispetto al DMV sys.objects:

select COUNT(*)
from sys.objects o
where o.type_desc like '%CONSTRAINT%';

Se sei interessato a elencare le tabelle, potresti eseguire qualcosa del genere:

select distinct
   o.object_id
 , QUOTENAME(s.name) + '.' + QUOTENAME(o.name) as [object_name]
 , o.type_desc
 , case when dc.parent_object_id is null then 'No' else 'Yes' end as has_default_constraint
 , case when cc.parent_object_id is null then 'No' else 'Yes' end as has_check_constraint
 , case when fk.parent_object_id is null then 'No' else 'Yes' end as has_foreing_key
 , case when kc.parent_object_id is null then 'No' else 'Yes' end as has_primary_key
from sys.objects o
inner join sys.schemas s on s.schema_id = o.schema_id
left outer join sys.default_constraints dc on dc.parent_object_id = o.object_id and dc.schema_id = o.schema_id
left outer join sys.check_constraints cc on cc.parent_object_id = o.object_id and cc.schema_id = o.schema_id
left outer join sys.foreign_keys fk on fk.parent_object_id = o.object_id and fk.schema_id = o.schema_id
left outer join sys.key_constraints kc on kc.parent_object_id = o.object_id and kc.schema_id = o.schema_id
where o.is_ms_shipped = 0
  and o.type = 'U'
order by [object_name];

Questo dovrebbe darti le informazioni sui tuoi indici:

select o.name
 , i.*
from sys.objects o
inner join sys.indexes i on i.object_id = o.object_id
where o.is_ms_shipped = 0
  and i.object_id > 100
  and i.index_id > 0
order by o.name
   , i.index_id;
  • Index_Id = 0 - HEAP (non verrà visualizzato)
  • Index_Id = 1 - CLUSTERED
  • Index_Id> 1 - NONCLUSTER

potresti spiegare perché l'hai fatto object_id > 100?
Brianc,

@ bluevoodoo1 - non obbligatorio ma <100 sono gli oggetti di sistema ma poiché l'utilizzo di o.is_ms_shipped = 0, non dovrebbe comunque includerli. Basta giocare al sicuro, tutto qui
DenisT,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.