list of tables without indexes in sql 2008 - sql-server

How do I list tables without indexes in my SQL 2008 database?
Edit
I want the Schema name and the Table name.

This should cover what your looking for. i.e. tables that are heaps (no clustered index) and do not have any non-clustered indexes. It uses the new sys. table objects used in 2005/2008.
in addition, you probably want to look for tables that do have a clustered index, but have no nonclustered indexes (this is the 2nd part of the statement which I've left commented out.
SELECT
schemaname = OBJECT_SCHEMA_NAME(o.object_id)
,tablename = o.NAME
FROM sys.objects o
INNER JOIN sys.indexes i ON i.OBJECT_ID = o.OBJECT_ID
-- tables that are heaps without any nonclustered indexes
WHERE (
o.type = 'U'
AND o.OBJECT_ID NOT IN (
SELECT OBJECT_ID
FROM sys.indexes
WHERE index_id > 0
)
)
-- OR
-- table that have a clustered index without any nonclustered indexes
--(o.type='U'
-- AND o.OBJECT_ID NOT IN (
-- SELECT OBJECT_ID
-- FROM sys.indexes
-- WHERE index_id>1))

Here's an example:
select SCHEMA_NAME(schema_id), name from sys.tables
where OBJECTPROPERTY(object_id, 'IsIndexed')= 0

In addition to #Philip Fourie's suggestion you might want to think about which indexes to create.
Once you have been accessing your data, SQL Server 2008 keeps track of places where it thinks indexes will be helpful (it refers to these as "missing indexes." There are a hand full of new Dynamic Managed Views which can show these missing indexes and some info about them.
From MSSQlTips:
sys.dm_db_missing_index_details - Returns detailed information about a missing index
sys.dm_db_missing_index_group_stats - Returns summary information about missing index groups
sys.dm_db_missing_index_groups - Returns information about a specific group of missing indexes
sys.dm_db_missing_index_columns(index_handle) - Returns information about the database table columns that are missing for an index. This is a function and requires the index_handle to be passed.

select shema = s.name, table_name = o.name
from sys.objects o
join sys.schemas s on o.schema_id = s.schema_id
where type = 'U'
and not exists (select i.index_id
from sys.indexes i
where i.type <> 0 --ignore default heap index row
and o.object_id = i.object_id )
Edit:
I have updated the SQL to include the Schema name as requested. (Note I had to sys.objects instead of sysobjects to cater for schemas that were introduced in SQL 2005)
The catalog tables are documented in the SQL Server documentation, see this link.
This FAQ contains more samples and might also be useful.
Note that these are system tables and can change between SQL server versions, where possible rather use the system table-independent views called Information Schema Views.

This code gives all the details about the indexes for all the tables:
SELECT
sch.name AS [Schema],
obj.name AS TableName,
indx.name AS IndexName,
CASE
WHEN indx.type_desc = 'HEAP' THEN 'N/A'
ELSE indx.type_desc
END AS IndexType
FROM sys.objects obj
JOIN sys.indexes indx ON indx.object_id = obj.object_id
JOIN sys.schemas AS sch ON sch.schema_id = obj.schema_id
WHERE
obj.type = 'U'
ORDER BY
obj.name

Related

How to identify all the tables that have (or don't have) a unique index?

What is the most efficient way in SQL Server to identify all tables that have a unique index?
This has been addressed elsewhere for Oracle: https://stackoverflow.com/a/28740458/3112914
My end goal is to identify tables in a database that can not be compared using SSDT Data Compare tool. For that tool to work "Tables must have the same primary key, unique index, or unique constraint." I can identify those with primary key or unique constraint using OBJECTPROPERTY, e.g.
SELECT
SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName,
OBJECTPROPERTY(OBJECT_ID,'TableHasPrimaryKey') AS HasPrimaryKey,
OBJECTPROPERTY(OBJECT_ID,'TableHasUniqueCnst') AS HasUniqueConstraint
FROM
sys.tables
There is an IsIndexed property but that doesn't say that is a unique index. https://learn.microsoft.com/en-us/sql/t-sql/functions/objectproperty-transact-sql?view=sql-server-2017
If you want to list all the tables that have a unique index you can join to sys.indexes and filter using column is_unique.
e.g.
-- list of tables that have a unique index
SELECT SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName
FROM
sys.tables
WHERE EXISTS (SELECT *
FROM sys.indexes i
WHERE i.object_id = tables.object_id AND is_unique = 1)
If you want to extend the show every table, along with a value indicating whether or not it has a unique index (ie extend the start you had above), you can wrap that EXISTS statement in an IIF or CASE, like this :
SELECT SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName,
OBJECTPROPERTY(OBJECT_ID, 'TableHasPrimaryKey') AS HasPrimaryKey,
OBJECTPROPERTY(OBJECT_ID, 'TableHasUniqueCnst') AS HasUniqueConstraint,
CASE
WHEN EXISTS (
SELECT *
FROM sys.indexes i
WHERE i.object_id = tables.object_id
AND is_unique = 1
)
THEN 1
ELSE 0
END AS HasUniqueIndex
FROM sys.tables

Check if any database table has any rows

I am trying to understand how to check if any table in my db has data using entity framework. I can check for one table but how can I check for all tables at once? DO we have any option with ef6?
using (var db = new CreateDbContext())
{
if(!db.FirstTable.Any())
{
// The table is empty
}
}
Any pointers on how to loop through entities would be helpful.
Here is one way you could do this with t-sql. This should be lightning fast on most systems. This returned in less than a second on our ERP database. It stated 421 billion rows in more than 15,000 partition stats.
select sum(p.row_count)
from sys.dm_db_partition_stats p
join sys.objects o on o.object_id = p.object_id
where o.type not in ('S', 'IT') --excludes system and internal tables.
Similar to #SeanLange, but shows schema name and table name for tables without any rows.
SELECT Distinct OBJECT_SCHEMA_NAME(p.object_id) AS [Schema],
OBJECT_NAME(p.object_id) AS [Table]
FROM sys.partitions p
INNER JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
WHERE OBJECT_SCHEMA_NAME(p.object_id) != 'sys'
And p.Rows = 0
ORDER BY [Schema], [Table]

given a foreign key, how do i find all tables that use that particular key?

i have a column (myColumn) that serves as the primary key of a table (tableA).
i've noticed that 2 or 3 tables reference this myColumn as foreign key.
how do i detect all tables that use and reference myColumn?
im guessing that more than 3 tables use myColumn because when i tried updating it like this
UPDATE tableA
SET myColumn = 1
WHERE myColumn = 1
6 rows were updated.
it was earlier suggested to me to use
sp_helpconstraint('your_table_name')
but i then found out that this does not give the complete information that i need.
any other suggestions?
Try this - this is the more up-to-date, SQL Server 2005 and newer version of my original answer that Mitch linked to (that was for SQL Server 2000):
SELECT
ConstraintName = fk.name,
TableName = t.name,
ColumnName = c.name
FROM
sys.foreign_keys fk
INNER JOIN
sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
INNER JOIN
sys.tables t ON fk.parent_object_id = t.object_id
INNER JOIN
sys.columns c ON fkc.parent_object_id = c.object_id AND fkc.parent_column_id = c.column_id
INNER JOIN
sys.tables tref ON fk.referenced_object_id = tref.object_id
INNER JOIN
sys.columns cref ON fkc.referenced_object_id = cref.object_id AND fkc.referenced_column_id = cref.column_id
WHERE
tref.Name = 'Person'
AND cref.Name = 'OID'
It uses the system catalog views sys.foreign_keys and sys.foreign_key_columns to find out which tables/columns reference that table and column you're interested in.
You just basically type in the table name and the column name in the WHERE clause - and you get your list of other tables/columns referencing that table/column
If you install Redgate's free sql search tool you can easily search your database schema for strings such as tables and column names.
http://www.red-gate.com/products/sql-development/sql-search/
There are other ways to search the schema using system tables but I highly recommend this tool. It will become part of your everyday workflow if you are constantly reverse engineering large databases.

Why does the sys.indexes table have a NULL Index name?

I ran this query:
SELECT
i.name AS IndexName,
s.used_page_count * 8 AS IndexSizeKB
FROM sys.dm_db_partition_stats AS s
JOIN sys.indexes AS i
ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
WHERE s.[object_id] = object_id('dbo.Stu')
ORDER BY i.name
and the largest index returned had a NULL name. What does this mean?
From sys.indexes:
Name of the index...
NULL = Heap
So those are heaps.
The sys.indexes view shows not only indexes, but also tables which don't have indexes on them. Such tables are called heaps. In such case, there is no name of the index. This can be misleading, I agree.
SELECT i.object_id, i.type_desc,
i.name AS IndexName,
s.used_page_count * 8 AS IndexSizeKB
FROM sys.dm_db_partition_stats AS s
JOIN sys.indexes AS i
ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
WHERE s.[object_id] = object_id('dbo.Stu')
ORDER BY i.object_id, i.name
Basically if the query you posted returns NULL index name, it means there is no clustered index on your table dbo.Stu.
I would recommend creating a clustered index on the table.
Imortant addition to above answers:
Index name in sys.indexes catalog view can be NULL in TWO cases:
1) As specified in MSDN, if it is actually a heap, i.e. table has no clustered index. For each nunclustered table there is one such a record in sys.indexes view (even if table has other, nonclustered indexes).
2) If this is a statistic (MSDN surprisingly keeps silence about this!). At least, I observed such a condition on one of my databases under SQL 2008 R2 server.

How do I get a list of tables affected by a set of stored procedures?

I have a huge database with some 100 tables and some 250 stored procedures. I want to know the list of tables affected by a subset of stored procedures. For example, I have a list of 50 stored procedures, out of 250, and I want to know the list of tables that will be affected by these 50 stored procedures. Is there any easy way for doing this, other than reading all the stored procedures and finding the list of tables manually?
PS: I am using SQL Server 2000 and SQL Server 2005 clients for this.
This would be your SQL Server query:
SELECT
[NAME]
FROM
sysobjects
WHERE
xType = 'U' AND --specifies a user table object
id in
(
SELECT
sd.depid
FROM
sysobjects so,
sysdepends sd
WHERE
so.name = 'NameOfStoredProcedure' AND
sd.id = so.id
)
Hope this helps someone.
sp_depends 'StoredProcName' will return the object name and object type that the stored proc depends on.
EDIT: I like #KG's answer better. More flexible IMHO.
I'd do it this way in SQL 2005 (uncomment the "AND" line if you only want it for a particular proc):
SELECT
[Proc] = SCHEMA_NAME(p.schema_id) + '.' + p.name,
[Table] = SCHEMA_NAME(t.schema_id) + '.' + t.name,
[Column] = c.name,
d.is_selected,
d.is_updated
FROM sys.procedures p
INNER JOIN sys.sql_dependencies d
ON d.object_id = p.object_id
AND d.class IN (0,1)
INNER JOIN sys.tables t
ON t.object_id = d.referenced_major_id
INNER JOIN sys.columns c
ON c.object_id = t.object_id
AND c.column_id = d.referenced_minor_id
WHERE p.type IN ('P')
-- AND p.object_id = OBJECT_ID('MyProc')
ORDER BY
1, 2, 3
One very invasive option would be to get a duplicate database and set a trigger on every table that logs that something happened. Then run all the SP's. If you can't do lots of mods to the DB that wont work
Also, be sure to add the logging to existing triggers rather than replace them with logging if you also want tables that the SP's effect via triggers.

Resources