views:

671

answers:

4

Where I'm at we have a software package running on a mainframe system. The mainframe makes a nightly dump into sql server, such that each of our clients has it's own database in the server. There are a few other databases in the server instance as well, plus some older client dbs with no data.

We often need to run reports or check data across all clients. I would like to be able to run queries using sp_msforeachdb or something similar, but I'm not sure how I can go about filtering unwanted dbs from the list. Any thoughts on how this could work?

We're still on SQL Server 2000, but should be moving to 2005 in a few months.


Update:
I think I did a poor job asking this question, so I'm gonna clarify my goals and then post the solution I ended up using.

What I want to accomplish here is to make it easy for programmers working on queries for use in their programs to write the query using one client database, and then pretty much instantly run (test) code designed and built on one client's db on all 50 or so client dbs, with little to no modification.

With that in mind, here's my code as it currently sits in Management Studio (partially obfuscated):

use [master]
declare @sql varchar(3900) 

set @sql = 'complicated sql command added here'

-----------------------------------
declare @cmd1 varchar(100)
declare @cmd2 varchar(4000)
declare @cmd3 varchar(100)
set @cmd1 = 'if ''?'' like ''commonprefix_%'' raiserror (''Starting ?'', 0, 1) with nowait'
set @cmd3 = 'if ''?'' like ''commonprefix_%'' print ''Finished ?'''
set @cmd2 = 
    replace('if ''?'' like ''commonprefix_%'' 
    begin 
     use [?]
     {0} 
    end', '{0}', @sql)

exec sp_msforeachdb @command1 = @cmd1, @command2 = @cmd2, @command3 = @cmd3

The nice thing about this is all you have to do is set the @sql variable to your query text. Very easy to turn into a stored procedure. It's dynamic sql, but again: it's only used for development (famous last words ;) ). The downside is that you still need to escape single quotes used in the query and much of the time you'll end up putting an extra ''?'' As ClientDB column in the select list, but otherwise it works well enough.

Unless I get another really good idea today I want to turn this into a stored procedure and also put together a version as a table-valued function using a temp table to put all the results in one resultset (for select queries only).

A: 

Each of our database servers contains a "DBA" database that contains tables full of meta-data like this.

A "databases" table would keep a list of all databases on the server, and you could put flag columns to indicate database status (live, archive, system, etc).

Then the first thing your SCRIPT does is to go to your DBA database to get the list of all databases it should be running against.

We even have a nightly maintenance script that makes sure all databases physically on the server are also entered into our "DBA.databases" table, and alerts us if they are not. (Because adding a row to this table should be a manual process)

BradC
A: 

How about taking the definition of sp_msforeachdb, and tweaking it to fit your purpose? To get the definition you can run this (hit ctrl-T first to put the results pane into Text mode):

sp_helptext sp_msforeachdb

Obviously you would want to create your own version of this sproc rather than overwriting the original ;o)

Paul Nearney
+1  A: 

Just wrap the statement you want to execute in an IF NOT IN:

EXEC    sp_msforeachdb  "
IF      '?'     NOT IN ('DBs','to','exclude')   BEGIN
        EXEC    sp_whatever_you_want_to
END
"
entaroadun
I ended up going with a solution very similar to this.
Joel Coehoorn
A: 

Doing this type of thing is pretty simple in 2005 SSIS packages. Perhaps you could get an instance set up on a server somewhere.

We have multiple servers set up, so we have a table that denotes what servers will be surveyed. We then pull back, among other things, a list of all databases. This is used for backup scripts.

You could maintain this list of databases and add a few fields for your own purposes. You could have another package or step, depending on how you decide which databases to report on and if it could be done programmatically.

You can get code here for free: http://www.sqlmag.com/Articles/ArticleID/97840/97840.html?Ad=1

We based our system on this code.

Sam