2013-08-27 2 views
24

У меня (для целей тестирования) много dbs с той же схемой (= одинаковые таблицы и столбцы в основном) на экземпляре r2 сервера sql server 2008 r2.Как запустить один и тот же запрос во всех базах данных экземпляра?

я хотел бы запрос как

SELECT COUNT(*) FROM CUSTOMERS 

по всем блокам данных на экземпляре. Я хотел бы иметь в качестве результата 2 колонки:

1 - БД Имя

2 - значение COUNT(*)

Пример:

DBName // COUNT (*) 

TestDB1 // 4 

MyDB // 5 

etc... 

Примечание: я считать, что CUSTOMERS таблица существует во всех dbs (кроме master).

ответ

31

Попробуйте один -

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 

вывода (например, в AdventureWorks) -

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

Привет, Devart, я использую этот sql и отлично работает. Но можно ли добавить проверку, если пользователь, выполняющий этот запрос, имеет доступ к каждой базе данных или нет, а если нет, запрос должен продолжать работать и возвращать только базы данных, к которым пользователь имеет доступ. То, что я получаю, - это то, имеет ли пользователь разрешение на роль БДО на каждой базе данных, и если не переходить на следующий, пожалуйста, можете ли вы посоветовать. – DK2014

23

прямой запрос

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

Этот запрос покажет вам, что вы хотите увидеть, но и бросать ошибки для каждой БД без стола под названием «КЛИЕНТЫ». Вам нужно будет разработать логику, чтобы справиться с этим.

Радж

+1

+1 это очень компактное решение, но я ose the other, так как ваше решение разбивает многие таблицы результатов, в то время как другое не – LaBracca

+3

Возможно, стоит упомянуть, что sp_MSForEachDB недокументирован, неподдерживается и имеет некоторые известные проблемы, как обсуждал Аарон Бертран здесь http://sqlblog.com/blogs/aaron_bertrand /archive/2010/12/29/a-more-reliable-and-more-flexible-sp-msforeachdb.aspx. –

5

Как о чем-то вроде этого:

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

Это полезный общий фрагмент, я просто заменил 'sys.databases'' 'sys.tables' для совершенно другой цели, используя тот же шаблон. –

+2

Вы забыли в сценарии объявить [at] db_name, вам нужно добавить одну строку: DECLARE @db_name NVARCHAR (150), в противном случае очень полезный скрипт :-) – inkubpl

+0

Где находится таблица temp delcared? – Phil3992

 Смежные вопросы

  • Нет связанных вопросов^_^