SQL Server show list of tables from a database with a parameter for the Database name

databarracks
databarracks used Ask the Experts™
on
Hi Guys,

I have the below query that shows a list of tables and number of rows and total space in GB. This query works really well, however I would like to create a stored procedure whereby I can add a parameter to choose what database on the same server to query?

Currently this query would only work based on the current database that I am in.  Basically the premise is that I have a simple application where an admin can change the database name via a dropdown and that will show the below queries results bases on the db name selected.

I don't know how to create a stored proc without hardcoding an if statement to set the 'USE' statement. I would rather avoid dynamic sql if that makes sense but Google seems to be pointing that way. If I have to then so be it:)

I would kindly appreciate any assistance in helping me resolve this issue?

SELECT    s.name + '.' + t.name AS [Table Name], part.rows AS [Total Rows In Table - Modified], CAST(SUM(DISTINCT au.total_pages) 
                         * 8 / 1024.000 / 1024.000 AS NUMERIC(18, 3)) AS [Table's Total Space In GB]
FROM            sys.tables AS t INNER JOIN
                         sys.schemas AS s ON t.schema_id = s.schema_id INNER JOIN
                         sys.indexes AS idx ON t.object_id = idx.object_id INNER JOIN
                         sys.partitions AS part ON idx.object_id = part.object_id AND idx.index_id = part.index_id INNER JOIN
                         sys.allocation_units AS au ON part.partition_id = au.container_id INNER JOIN
                         sys.filegroups AS fGrp ON idx.data_space_id = fGrp.data_space_id INNER JOIN
                         sys.database_files AS Df ON Df.data_space_id = fGrp.data_space_id
WHERE        (t.is_ms_shipped = 0) AND (idx.object_id > 255)
GROUP BY t.name, s.name, part.rows
ORDER BY [Table's Total Space In GB] DESC

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Not hugely encouraged by anybody, but here is what you are looking for.

Author

Commented:
Hi Nitin,

Thanks for that, however as you explicitly mentioned if it is not encouraged then I won't bother :(. Thanks for the tip so I can safely conclude that it isn't possible then?
Vitor MontalvãoIT Engineer
Distinguished Expert 2017

Commented:
A stored procedure is part of a database, so or you create it in the master database and use a dynamic query where you can change the database by using the USE command or you can have the same stored procedure replicated to every database and then you can call it like this:
EXEC database.dbo.sp_name

Open in new window

Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

It is definitely possible. Did you refer to the hyperlink I posted. All I was mentioning what is written at the end of that article.

It should be noted that adding objects to the master database is not generally considered a good practice, so I don't make use of this feature on production servers.

Author

Commented:
Hi Vitor,

I did think of that approach but would you be kind as to elaborate on how I could declare the DB name in the stored proc within the master database?

Author

Commented:
Ahh I see what you mean Nitin.
Vitor MontalvãoIT Engineer
Distinguished Expert 2017

Commented:
Personally, I don't have nothing against creating objects in master database. Especially if they intended to perform generic tasks.
What most of DBAs do, is to creating their private database in all SQL Server instances that they manage so they can use it for this kind of stuffs that will help with their daily tasks.
Vitor MontalvãoIT Engineer
Distinguished Expert 2017

Commented:
I did think of that approach but would you be kind as to elaborate on how I could declare the DB name in the stored proc within the master database?
It's only creating a dynamic SQL:
CREATE PROC sp_getFileSizes (@DB_Name AS system)
AS

DECLARE @MySQL VARCHAR(MAX)

SET @MySQL = 'USE ' + @DB_Name + '

SELECT    s.name + ''.'' + t.name AS [Table Name], part.rows AS [Total Rows In Table - Modified], CAST(SUM(DISTINCT au.total_pages) 
                         * 8 / 1024.000 / 1024.000 AS NUMERIC(18, 3)) AS [Tables Total Space In GB]
FROM            sys.tables AS t INNER JOIN
                         sys.schemas AS s ON t.schema_id = s.schema_id INNER JOIN
                         sys.indexes AS idx ON t.object_id = idx.object_id INNER JOIN
                         sys.partitions AS part ON idx.object_id = part.object_id AND idx.index_id = part.index_id INNER JOIN
                         sys.allocation_units AS au ON part.partition_id = au.container_id INNER JOIN
                         sys.filegroups AS fGrp ON idx.data_space_id = fGrp.data_space_id INNER JOIN
                         sys.database_files AS Df ON Df.data_space_id = fGrp.data_space_id
WHERE        (t.is_ms_shipped = 0) AND (idx.object_id > 255)
GROUP BY t.name, s.name, part.rows
ORDER BY [Tables Total Space In GB] DESC'

EXEC @MySQL

Open in new window

Author

Commented:
Hi Vitor,

Thanks for the stored proc, I am getting an error on the parameter variale @DB_Name has  an invalid type. I am guessing it should be a VARCHAR(256)??
IT Engineer
Distinguished Expert 2017
Commented:
Sorry, didn't test it. Here's the correct version:
CREATE PROC sp_getFileSizes (@DB_Name AS VARCHAR(MAX))
AS

DECLARE @MySQL VARCHAR(MAX)

SET @MySQL = 'USE ' + @DB_Name + '

SELECT    s.name + ''.'' + t.name AS [Table Name], part.rows AS [Total Rows In Table - Modified], CAST(SUM(DISTINCT au.total_pages) 
                         * 8 / 1024.000 / 1024.000 AS NUMERIC(18, 3)) AS [Tables Total Space In GB]
FROM            sys.tables AS t INNER JOIN
                         sys.schemas AS s ON t.schema_id = s.schema_id INNER JOIN
                         sys.indexes AS idx ON t.object_id = idx.object_id INNER JOIN
                         sys.partitions AS part ON idx.object_id = part.object_id AND idx.index_id = part.index_id INNER JOIN
                         sys.allocation_units AS au ON part.partition_id = au.container_id INNER JOIN
                         sys.filegroups AS fGrp ON idx.data_space_id = fGrp.data_space_id INNER JOIN
                         sys.database_files AS Df ON Df.data_space_id = fGrp.data_space_id
WHERE        (t.is_ms_shipped = 0) AND (idx.object_id > 255)
GROUP BY t.name, s.name, part.rows
ORDER BY [Tables Total Space In GB] DESC'

EXEC(@MySQL)
GO

Open in new window

Author

Commented:
Do you know why I cannot see the sp in my viewer on SSMS?
Vitor MontalvãoIT Engineer
Distinguished Expert 2017

Commented:
You might need to refresh the SSMS.
@databarracks, however, from your original post, I gather you were averse to dynamic sql. Not too keen to use it if it is the only option available.

Author

Commented:
Yes I was, what I was trying to say is that if it was the only option then I would use it..hence 'If I have to then so be it:)'

Author

Commented:
Again this is something that is only used by 3 people within the organisation nothing public about it
Vitor MontalvãoIT Engineer
Distinguished Expert 2017

Commented:
I can't see another way besides the ones I've explained.

Author

Commented:
I am happy with it and have created the sp in another database as means of 'best practises' because they say not to create new objects in the master db.

Author

Commented:
Thank you to Vitor and Nitin for helping me out on this issue. Nitin assisted me in providing a useful link and Vitor provided the final solution of which I chose to use in my environment as it was a direct improvement of my original query

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial