2013-08-27 19 views
24

Mam (do testowania) wiele dbs z tym samym schematem (= same tabele i kolumny w zasadzie) na serwerze sql 2008 r2 instancji.Jak uruchomić to samo zapytanie we wszystkich bazach danych instancji?

chciałbym zapytać jak

SELECT COUNT(*) FROM CUSTOMERS 

na wszystkich DB na przykład. Chciałbym mieć jako wynik 2 kolumny:

1 - DB Nazwa

2 - wartość COUNT(*)

Przykład:

DBName // COUNT (*) 

TestDB1 // 4 

MyDB // 5 

etc... 

Uwaga: Zakładam, że CUSTOMERS tabela istnieje we wszystkich dbs (z wyjątkiem master).

Odpowiedz

31

Spróbuj ten -

SET NOCOUNT ON; 

IF OBJECT_ID (N'tempdb.dbo.#temp') IS NOT NULL 
    DROP TABLE #temp 

CREATE TABLE #temp 
(
     [COUNT] INT 
    , DB VARCHAR(50) 
) 

DECLARE @TableName NVARCHAR(50) 
SELECT @TableName = '[dbo].[CUSTOMERS]' 

DECLARE @SQL NVARCHAR(MAX) 
SELECT @SQL = STUFF((
    SELECT CHAR(13) + 'SELECT ''' + name + ''', COUNT(1) FROM [' + name + '].' + @TableName 
    FROM sys.databases 
    WHERE OBJECT_ID(name + '.' + @TableName) IS NOT NULL 
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 

INSERT INTO #temp (DB, [COUNT])    
EXEC sys.sp_executesql @SQL 

SELECT * 
FROM #temp t 

Output (na przykład w AdventureWorks) -

COUNT  DB 
----------- -------------------------------------------------- 
19972  AdventureWorks2008R2 
19975  AdventureWorks2012 
19472  AdventureWorks2008R2_Live 
+0

Cześć Devart, używam tego sql i działa świetnie. Ale czy możliwe jest dodanie sprawdzenia, jeśli użytkownik uruchamiający to zapytanie ma dostęp do każdej bazy danych, a jeśli nie, zapytanie powinno nadal działać i zwracać tylko te bazy danych, do których użytkownik ma dostęp. Pytam tylko o to, czy użytkownik ma uprawnienia do roli DBO w każdej z baz danych, a jeśli nie, przejdź do następnej. Czy możesz doradzić? – DK2014

23

Proste zapytanie do przodu

EXECUTE sp_MSForEachDB 
     'USE ?; SELECT DB_NAME()AS DBName, 
     COUNT(1)AS [Count] FROM CUSTOMERS' 

To zapytanie pokaże Ci, co chcesz zobaczyć, ale także rzucać błędów dla każdego DB bez tabeli o nazwie „Klienci”. Będziesz musiał opracować logikę, aby sobie z tym poradzić.

Raj

+1

+1 to bardzo kompaktowe rozwiązanie, ale ja cho Z drugiej strony, ponieważ rozwiązanie rozwiązuje wiele tablic wyników, podczas gdy inne nie. – LaBracca

+3

Warto wspomnieć, że sp_MSForEachDB jest nieudokumentowanym, nieobsługiwanym i ma kilka znanych problemów omawianych przez Aarona Bertranda tutaj http://sqlblog.com/blogs/aaron_bertrand /archive/2010/12/29/a-more-reliable-and-more-flexible-sp-msforeachdb.aspx. –

5

Jak o coś takiego:

DECLARE c_db_names CURSOR FOR 
SELECT name 
FROM sys.databases 
WHERE name NOT IN('master', 'tempdb') --might need to exclude more dbs 

OPEN c_db_names 

FETCH c_db_names INTO @db_name 

WHILE @@Fetch_Status = 0 
BEGIN 
    EXEC(' 
    INSERT INTO #report 
    SELECT 
     ''' + @db_name + ''' 
     ,COUNT(*) 
    FROM ' + @db_name + '..linkfile 
    ') 
    FETCH c_db_names INTO @db_name 
END 

CLOSE c_db_names 
DEALLOCATE c_db_names 

SELECT * FROM #report 
+0

Jest to przydatny ogólny fragment, właśnie zamieniłem 'sys.databases' na' sys.tables' dla bardzo różnych celów, używając tego samego zestawu znaków. –

+2

Zapomniałeś w skrypcie, aby zadeklarować [at] db_name, musisz dodać jedną linię: DECLARE @db_name NVARCHAR (150), w przeciwnym razie bardzo przydatny skrypt :-) – inkubpl

+0

Gdzie jest tablica tymczasowa zagubiona? – Phil3992