问题
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!
回答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.
来源:https://stackoverflow.com/questions/34131733/sql-run-query-across-multiple-databases