0

I am looking to run a query over multiple databases. I've seen this function;

sp_MsForEachDb

Which is ok, but it runs through all the databases and I only want to use some of them. Is there a way to select which databases are run? Also within those databases, we have branches (so all the tables have a BranchID column). For example, Database 1 might have branches 4, 5 and 6 and we only want branch 5. Database 2 might also have branches 4, 5 and 6, but in this one we want branches 4 and 5. Is there a way to select which branch is run according to which database is being run?

COuld this be done on SSIS or something similar?

Hope this makes sense!

jarlh
  • 42,561
  • 8
  • 45
  • 63
Becky
  • 115
  • 2
  • 18

1 Answers1

1

I use a simple cursor to accomplish this....it's pretty straight forward and you can run any statement within it, against the list of databases.

    --Drop temporary tables if they already exists.
IF OBJECT_ID('tempdb..#DatabaseNames') IS NOT NULL
    DROP TABLE #DatabaseNames

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    DROP TABLE #Results

--Create a temporary table.
CREATE TABLE #DatabaseNames
(
    DBName varchar(100),
    Active bit
)

GO

--Create a temporary table to store results.
CREATE TABLE #Results
(
    FirstName varchar(100),
    WebLogin varchar(100)
)

GO

--It's the long way to do this but just showing for the sake of the example.
INSERT INTO #DatabaseNames
VALUES ('Database1', 1)

INSERT INTO #DatabaseNames
VALUES ('Database2', 0)

INSERT INTO #DatabaseNames
VALUES ('Database3', 1)

INSERT INTO #DatabaseNames
VALUES ('TIER1', 1)

INSERT INTO #DatabaseNames
VALUES ('Northwind', 1)

DECLARE @DBName varchar(20)
DECLARE @SQL   varchar(2000)

--Start cursor
DECLARE LoopCursor CURSOR FOR
    SELECT DBName AS 'DBName'
    FROM #DatabaseNames
    WHERE DBName NOT IN ('TIER1', 'Northwind')
    AND Active = 1

    OPEN LoopCursor

    FETCH NEXT FROM LoopCursor
    INTO @DBName

    WHILE @@FETCH_STATUS = 0
    BEGIN

        SET @SQL = '
        INSERT INTO #Results
        SELECT FirstName, WebLogin
        FROM ' + @DBName + '.dbo.Users
        WHERE FirstName = ''User1''
        AND LastName = ''User1''
        AND WebLogin = ''User1Login'''

        EXEC(@SQL)
        --Print @DBName

        FETCH NEXT FROM LoopCursor
        INTO @DBName
    END

    SELECT *
    FROM #Results

    CLOSE LoopCursor
    DEALLOCATE LoopCursor

I modified my answer again to go with your last comment about wanting all the results in one table. You can add another temporary table and just insert the data into that. Then once done, select from that table before closing the cursor. As for having many criteria in the WHERE clause, you can enclose single quotes with 2 singles quotes, so WHERE name = 'MyName' becomes WHERE name = ''MyName''

BTW, I cursors aren't the most CPU friendly and most don't like using them but they have their place. I'm not suggesting this is the best solution but it works well. We have over 75 customer databases, all having the same structure, and I use this daily to update user fields and other table fields. It runs pretty fast for executing so many statements on so many databases.

Robert
  • 1,696
  • 3
  • 36
  • 70
  • That looks really useful. What could I replace the configuration table with as I don't have one? – Becky Dec 07 '15 at 11:16
  • Ah I see. Is there any way to get the results to all be in one table instead of one per database. Union All or something. Otherwise I'm going to have to copy and paste every single table into excel (and there's about 75). – Becky Dec 07 '15 at 12:11
  • Are the fields all the same from each database? – Robert Dec 07 '15 at 12:18
  • yes they are so that should be fine. Also I have a lot of date criteria in the where clauses, how do I get them in, given they need single quote marks? Thank you so much for your help with this! – Becky Dec 07 '15 at 12:20