I have a database named test
which contains 2 views and 2 tables under the schema dbo
:
I want to create a table named report
which lists the number of rows for each view and each table. The concept is like this:
select table_name, table_type, "select count(*) from table_name" as rowCount
into test.dbo.report
from test.INFORMATION_SCHEMA.tables;
The expected output (test.dbo.report
) should look like this:
I am still trying with Dynamic SQL but having no luck so far.
I am using SQL Server 2014.
You can use dynamic SQL to build a giant chain of union all select
statements:
declare @sql nvarchar(max) = ''
-- use an undocumented(?) trick with string concatenation in a select statement
select @sql = @sql + 'union all select ' +
'''' + TABLE_NAME + ''' as TABLE_NAME, ' +
'''' + TABLE_TYPE + ''' as TABLE_TYPE, ' +
'(select count(*) from ' + TABLE_NAME + ') as [COUNT]' +
char(13) + char(10)
from INFORMATION_SCHEMA.TABLES
-- remove leading "union all"
set @sql = right(@sql, len(@sql)-len('union all '))
--print @sql -- to check what's going to be executed
exec sp_executesql @sql
The SQL it builds and executes looks like:
select 'customers' as TABLE_NAME, 'BASE TABLE' as TABLE_TYPE, (select count(*) from customers) as [rowcount]
union all select 'items' as TABLE_NAME, 'BASE TABLE' as TABLE_TYPE, (select count(*) from items) as [rowcount]
union all select 'orders' as TABLE_NAME, 'VIEW' as TABLE_TYPE, (select count(*) from orders) as [rowcount]
union all ...
Unfortunately you cannot execute dynamic SQL as a column in a select statement - there is nothing that would allow you to do anything as simple as:
select table_name, table_type, exec('select count(*) from ' + table_name) as [count]
into test.dbo.report -- /\== doesn't work
from test.INFORMATION_SCHEMA.tables;