Listado de índices y restricciones

10

Estoy mirando una base de datos de SQL Server para una aplicación que heredé. No he investigado SQL Server durante aproximadamente 10 años, así que tengan paciencia conmigo.

La tabla de la base de datos que estoy viendo tiene una bigint NOT NULLcolumna llamada id, sin embargo, cuando compruebo las restricciones, no veo ninguna, y lo mismo es cierto para todas las tablas de la base de datos.

¿Estoy en lo cierto al suponer que no hay una clave primaria ni una indexación (agrupada o no agrupada) en estas tablas?

Ejecuté las siguientes consultas y los resultados parecen confirmar mi sospecha:

//**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;
Ali Haider
fuente

Respuestas:

9

Estas dos consultas pueden ayudarte. El primero enumerará todas las tablas e índices en esas tablas en su base de datos. Si la tabla no aparece en la lista, no tiene ningún índice definido. Estas consultas asumen SQL Server versión 2005 o posterior.

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 segunda consulta informará para cada tabla la columna de identidad, si hay alguna en cada tabla de su base de datos.

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;

Para limitar las consultas a una tabla específica, agregue una WHEREcláusula similar a:

WHERE T.name = N'NAME-OF-TABLE'
Jeremy
fuente
2

No, algo es incorrecto.

La comprobación sys.indexesdebería devolver una fila incluso si su tabla no tiene índices. El montón todavía tiene un registro sys.indexescon un type_desc'HEAP' y un type0.

Creo que probablemente deba asegurarse de estar en el contexto de base de datos correcto desde entonces OBJECT_ID()y que sys.objectssea ​​específico de la base de datos.

Prueba esto:

USE MyDatabase

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

No estoy seguro de si está interesado en todas las restricciones, pero INFORMATION_SCHEMA.TABLE_CONSTRAINTS no parece devolver las restricciones DEFAULT - TABLE_CONSTRAINTS (Transact-SQL)

CHEQUEO, ÚNICO, LLAVE PRIMARIA, LLAVE EXTRANJERA

Esta consulta hará un recuento simple contra el DMV sys.objects:

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

Si está interesado en enumerar las tablas, puede ejecutar algo como esto:

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];

Este debería darle la información en sus índices:

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 (no aparecerá)
  • Index_Id = 1 - AGRUPADO
  • Index_Id> 1 - NO CLUSTRADO
DenisT
fuente
¿podrías explicar por qué lo has hecho object_id > 100?
brianc
@ bluevoodoo1: no es obligatorio, pero <100 son los objetos del sistema, pero dado que usar o.is_ms_shipped = 0, no debería incluirlos de todos modos. Solo jugando seguro, eso es todo
DenisT