I have a DB with lots of tables without use. I'd like to filter out the tables without any data. So I used a snippet How to fetch the row count for all tables by #ismetAlkan.
However, I want to filter out 0, so used something like this and it doesn't work.
USE [my_db]
GO
SELECT * FROM
(
SELECT SCHEMA_NAME(A.schema_id) + '.' +
A.Name, SUM(B.rows) AS 'RowCount'
FROM sys.objects A
INNER JOIN sys.partitions B ON A.object_id = B.object_id
WHERE A.type = 'U'
GROUP BY A.schema_id, A.Name
) AS Result
where Result.RowCount > 0
GO
Any help appreciated!
There are three problems.
SELECT * FROM
(
SELECT ObjectName = SCHEMA_NAME(obj.[schema_id])
+ '.' + obj.name,
[RowCount] = SUM(p.rows)
FROM sys.objects AS obj
INNER JOIN sys.partitions AS p
ON obj.[object_id] = p.[object_id]
WHERE obj.type = 'U'
GROUP BY obj.[schema_id], obj.name
) AS Result
WHERE Result.[RowCount] > 0;
When you move a query into a derived table, subquery, or CTE, all of the columns need to have names.
'Alias' should be [Alias] since the former makes it look like a string and that form is deprecated in some contexts.
As Larnu pointed out, ROWCOUNT needs to be escaped in all spots, not just one.
Related
I'm using the following t-sql code:
USE [my_database]
SELECT DISTINCT so.name
FROM syscomments sc
INNER JOIN sysobjects so ON sc.id=so.id
WHERE sc.TEXT LIKE '%table_name%'
in order to show all the Stored Procedures that use the table table_name.
I want do this work for all tables in my database.
How can I perform this task and organize the output?
This uses information schema for both tables, and stored procedures. You can change or get rid of ROUTINE_TYPE condition to add functions, and you can change table type to return views.
This answer produces its results by checking what tables a stored procedure depends on. I think this will be a much more accurate result then checking if a name is in the query text. If the procedure refers to a table in a comment section, then this result will not be returned in the first query, but will be in the second and other answers given.
SELECT t.TABLE_NAME, s.ROUTINE_NAME
FROM INFORMATION_SCHEMA.TABLES t
INNER JOIN INFORMATION_SCHEMA.ROUTINES s ON
s.ROUTINE_NAME IN (SELECT referencing_entity_name
FROM sys.dm_sql_referencing_entities(TABLE_SCHEMA + '.' + TABLE_NAME, 'OBJECT'))
AND s.ROUTINE_TYPE = 'PROCEDURE'
WHERE t.TABLE_TYPE = 'BASE TABLE'
edit: Here's how to get the dependencies without the function. (I like this method the best)
SELECT DISTINCT t.name [TableName], p.name [ProcedureName]
FROM sys.objects t
LEFT JOIN sys.sql_dependencies d ON
d.referenced_major_id = t.object_id
LEFT JOIN sys.objects p ON
p.object_id = d.object_id
AND p.type = 'p'
WHERE t.type = 'u'
If your specific use is to just find any string that matches a table name, below will work:
SELECT t.TABLE_NAME, s.ROUTINE_NAME
FROM INFORMATION_SCHEMA.TABLES t
INNER JOIN INFORMATION_SCHEMA.ROUTINES s
ON CHARINDEX(t.TABLE_NAME, s.ROUTINE_DEFINITION) > 0
AND s.ROUTINE_TYPE = 'PROCEDURE'
WHERE t.TABLE_TYPE = 'BASE TABLE'
You could do a JOIN on LIKE:
select * from INFORMATION_SCHEMA.TABLES t
join
(
SELECT DISTINCT so.name
FROM syscomments sc
INNER JOIN sysobjects so ON sc.id=so.id
) x on x.name like '%' + t.TABLE_NAME + '%'
Note that your query doesn't restrict to procs - you'll also get views, defaults, and other objects too. If you just want procs, you can add where so.xtype = 'P' to your inner query.
Another version that uses sys tables only:
select t.name as TableName, p.name as SPName
from sys.objects t
join sys.syscomments c
on c.text like '%' + t.name + '%'
join sys.objects p
on p.object_id = c.id
where t.type = 'U' -- user table
and p.type = 'P' -- procedure
You can also use the built in function that's been around at least since SQL 2005 and works for tables, views, and stored procedures. I get the same number of results as Daniel's answer above when checking dependencies on a table in a fairly enterprisy database.
sp_depends [TableName]
sp_depends [TableName.Column]
sp_depends [StoredProcedureName]
http://msdn.microsoft.com/en-us/library/ms189487(v=sql.90).aspx
I am developing a SQL sproc and I want to return the number of rows for each table. How could I rewrite this statement so that it will list number of rows from each table below?
SELECT COUNT(*)
FROM [test_setup_details_form_view] [tsdf]
JOIN [test_setup_header_form_view]
ON [test_setup_header_form_view].[test_setup_header_id]
= [tsdf].[test_setup_header_id]
JOIN [test_header_rv] [th] with(nolock)
ON [th].[test_setup_header_id]
= [test_setup_header_form_view].[test_setup_header_id]
JOIN [test_details_answers_expanded_view] [tdae]
ON [tdae].[test_setup_details_id] = [tsdf].[test_setup_details_id]
AND [th].[test_header_id] = [tdae].[test_header_id]
JOIN [event_log_rv] [e]
ON [e].[event_log_id] = [tdae].[event_log_id]
When I execute this statement, it just gives me the total rows after all of the joins.
If you are trying to just get counts for each of these tables irrespective of the joins:
SELECT
OBJECT_SCHEMA_NAME([object_id]),
OBJECT_NAME([object_id]),
c
FROM
(
SELECT [object_id],
c = SUM(row_count)
FROM
sys.dm_db_partition_stats -- no NOLOCK necessary
WHERE
index_id IN (0,1)
AND OBJECT_NAME([object_id]) IN
(
N'test_setup_details_from_view',
N'test_setup_header_from_view',
... etc etc. ...
)
GROUP BY [object_id]
) AS x;
Use count (distinct <columnname>) on a unique column for each table that you need to count.
From each table? Why not use the metadata tables then?
You are trying to do something in code that already exists in the metadata tables:
Select
schema_name(schema_id) + '.' + t.name as TableName
, i.rows
from sys.tables t (nolock)
join sys.sysindexes i (nolock) on t.object_id = i.id
and i.indid < 2
I have database A which contains a table (CoreTables) that stores a list of active tables within database B that the organization's users are sending data to.
I would like to be able to have a set-based query that can output a list of only those tables within CoreTables that are populated with data.
Dynamically, I normally would do something like:
For each row in CoreTables
Get the table name
If table is empty
Do nothing
Else
Print table name
Is there a way to do this without a cursor or other dynamic methods? Thanks for any assistance...
Probably the most efficient option is:
SELECT c.name
FROM dbo.CoreTables AS c
WHERE EXISTS
(
SELECT 1
FROM sys.partitions
WHERE index_id IN (0,1)
AND rows > 0
AND [object_id] = OBJECT_ID(c.name)
);
Just note that the count in sys.sysindexes, sys.partitions and sys.dm_db_partition_stats are not guaranteed to be completely in sync due to in-flight transactions.
While you could just run this query in the context of the database, you could do this for a different database as follows (again assuming that CoreTables does not include schema in the name):
SELECT c.name
FROM DatabaseA.CoreTables AS c
WHERE EXISTS
(
SELECT 1
FROM DatabaseB.sys.partitions AS p
INNER JOIN DatabaseB.sys.tables AS t
ON p.[object_id] = t.object_id
WHERE t.name = c.name
AND p.rows > 0
);
If you need to do this for multiple databases that all contain the same schema (or at least overlapping schema that you're capturing in aggregate in a central CoreTables table), you might want to construct a view, such as:
CREATE VIEW dbo.CoreTableCounts
AS
SELECT db = 'DatabaseB', t.name, MAX(p.rows)
FROM DatabaseB.sys.partitions AS p
INNER JOIN DatabaseB.sys.tables AS t
ON p.[object_id] = t.[object_id]
INNER JOIN DatabaseA.dbo.CoreTables AS ct
ON t.name = ct.name
WHERE p.index_id IN (0,1)
GROUP BY t.name
UNION ALL
SELECT db = 'DatabaseC', t.name, rows = MAX(p.rows)
FROM DatabaseC.sys.partitions AS p
INNER JOIN DatabaseC.sys.tables AS t
ON p.[object_id] = t.[object_id]
INNER JOIN DatabaseA.dbo.CoreTables AS ct
ON t.name = ct.name
WHERE p.index_id IN (0,1)
GROUP BY t.name
-- ...
GO
Now your query isn't going to be quite as efficient, but doesn't need to hard-code database names as object prefixes, instead it can be:
SELECT name
FROM dbo.CoreTableCounts
WHERE db = 'DatabaseB'
AND rows > 0;
If that is painful to execute you could create a view for each database instead.
In SQL Server, you can do something like:
SELECT o.name, st.row_count
FROM sys.dm_db_partition_stats st join
sys.objects o
on st.object_id = o.object_id
WHERE index_id < 2 and st.row_count > 0
By the way, this specifically does not use OBJECT_ID() or OBJECT_NAME() because these are evaluated in the current database. The above code continues to work for another database, using 3-part naming. This version also takes into account multiple partitions:
SELECT o.name, sum(st.row_count)
FROM <dbname>.sys.dm_db_partition_stats st join
<dbname>.sys.objects o
on st.object_id = o.object_id
WHERE index_id < 2
group by o.name
having sum(st.row_count) > 0
something like this?
//
foreach (System.Data.DataTable dt in yourDataSet.Tables)
{
if (dt.Rows.Count != 0) { PrintYourTableName(dt.TableName); }
}
//
This is a way you can do it, that relies on system tables, so be AWARE it may not always work in future versions of SQL. With that strong caveat in mind.
select distinct OBJECT_NAME(id) as tabName,rowcnt
from sys.sysindexes si
join sys.objects so on si.id=si.id
where indid=1 and so.type='U'
You would add to the where clause the tables you are interested in and rowcnt <1
I have sql server database with numerous tables, some no longer used so I want to remove them. All database interactivity is via stored procedure to these tables.
Is there a database sql script that I can use that will list all tables not referenced in any of the stored procedures in the database?
If SQL Server 2008 then the dependencies information is now reliable.
SELECT SCHEMA_NAME(t.schema_id),
t.name
FROM sys.tables t
WHERE is_ms_shipped = 0
AND NOT EXISTS (SELECT *
FROM sys.sql_expression_dependencies d
WHERE d.referenced_entity_name = t.name
AND (( is_ambiguous = 1 or is_caller_dependent=1)
OR
d.referenced_id = t.object_id) )
You can't do this if you use any dynamic T-SQL. Dynamic T-SQL won't show up in any investigation of object dependencies.
Instead, you can use the DMV sys.dm_db_index_usage_stats to find what objects haven't been referenced by any queries. Here's a query I did on SQLServerPedia for that:
http://sqlserverpedia.com/wiki/Find_Indexes_Not_In_Use
The query is designed for performance tuning indexes, so you'll need to tweak a few lines. Here's the modified query:
SELECT
o.name
, indexname=i.name
, i.index_id
, reads=user_seeks + user_scans + user_lookups
, writes = user_updates
, rows = (SELECT SUM(p.rows) FROM sys.partitions p WHERE p.index_id = s.index_id AND s.object_id = p.object_id)
, CASE
WHEN s.user_updates < 1 THEN 100
ELSE 1.00 * (s.user_seeks + s.user_scans + s.user_lookups) / s.user_updates
END AS reads_per_write
, 'DROP INDEX ' + QUOTENAME(i.name)
+ ' ON ' + QUOTENAME(c.name) + '.' + QUOTENAME(OBJECT_NAME(s.object_id)) as 'drop statement'
FROM sys.dm_db_index_usage_stats s
INNER JOIN sys.indexes i ON i.index_id = s.index_id AND s.object_id = i.object_id
INNER JOIN sys.objects o on s.object_id = o.object_id
INNER JOIN sys.schemas c on o.schema_id = c.schema_id
WHERE OBJECTPROPERTY(s.object_id,'IsUserTable') = 1
AND s.database_id = DB_ID()
ORDER BY reads
Keep in mind that this catches all indexes, and you'll need to sift through - some of your objects may be heaps, some may have clustered indexes, etc. I'll leave this as a wiki so someone more ambitious than me can edit it to build a deduped list. :-D
Check this discussion tsql script to find tables not being used by stored procedures, views, functions, etc?
And this article(listed from above discussion) http://www.mssqltips.com/tip.asp?tip=1294 discusses about SQL object dependencies.
Perhaps something along these lines:
select t.table_name
from INFORMATION_SCHEMA.TABLES t
where not exists (
select 1 from INFORMATION_SCHEMA.ROUTINES r
where object_definition(object_id(r.ROUTINE_NAME)) like '%'+t.TABLE_NAME+'%'
) order by t.TABLE_NAME
The first query lists table with the stored proc name that uses it.
The second query lists table with the number of stored procs using it.
-- list all tables / sprocs
select t.name [Table], p.name [StoredProc]
from sys.tables t
left join sys.procedures p on (OBJECT_DEFINITION(p.object_id)) like '%' + t.name + '%'
where t.type = 'U'
order by t.name, p.name
-- count stored procs using table
select t.name [Table], count(p.name) [Count]
from sys.tables t
left join sys.procedures p on (OBJECT_DEFINITION(p.object_id)) like '%' + t.name + '%'
where t.type = 'U'
group by t.name
order by t.name
Here's one you might try:
select
name
from
sys.tables t
left join
sys.sql_dependencies d
on
t.object_id =
d.referenced_major_id
where
d.referenced_major_id is null
Otherwise, here's a reference I've used in the past:
http://www.mssqltips.com/tip.asp?tip=1294
If performace isnt to much of a problem you could try the following.
Select Distinct Object_Name(ID)
From syscomments
Where ID Not In (Select ID From syscomments Where Text Like '%<TableName>%')
This will check each view, rule, default, trigger, CHECK constraint, DEFAULT constraint, and stored procedure within your database
Most of this code doesn't work if there are schemas other than "dbo", or if the user's default schema is not "dbo". Here's an update to one of the scripts to fix that:
select t.Table_Schema + '.' + t.table_name
from INFORMATION_SCHEMA.TABLES t
where not exists (
select 1 from INFORMATION_SCHEMA.ROUTINES r
where object_definition(object_id(r.routine_schema + '.' + r.ROUTINE_NAME)) like '%'+t.TABLE_NAME+'%'
) order by t.TABLE_NAME
I have a table (DB_TableInfo) in my DB like the following
TableId Type
859374678 R
579845658 B
478625849 R
741587469 E
.
.
.
this table represents all tables in my DB. What I wanna do is to write a query to select tables of Type 'R', get their Id and return the Name of the table belonging to that Id (the TableName column is not available in the specified table)
Can anybody help me out?
I wanna write a query similar to this one!
SELECT TableID = OBJECT_NAME FROM [DB_TableInfo] WHERE Type = 'R'
From the mention of sys.objects and use of square brackets I assume you are on SQL Server.
You can use the object_name function.
SELECT OBJECT_NAME(TableID) /*Might match objects that aren't tables as well though*/
FROM [DB_TableInfo]
WHERE Type = 'R'
Or join onto sys.tables
SELECT T.name
FROM [DB_TableInfo] D
join sys.tables T ON D.TableID = T.object_id
WHERE D.Type = 'R'
And to exclude empty tables
SELECT t.name
FROM DB_TableInfo d
JOIN sys.tables t ON d.TableId = t.object_id
JOIN sys.dm_db_partition_stats ps ON ps.object_id = t.object_id
WHERE d.Type = 'R' and ps.index_id <= 1
GROUP BY d.TableId, t.name
HAVING SUM(ps.row_count) > 0