Я пишу хранимую процедуру, которая принимает имя базы данных в качестве аргумента и возвращает таблицу индексов этой базы данных и их уровень фрагментации. Эта хранимая процедура будет храниться в нашей базе данных DBA (база данных, содержащая таблицы, которые используются администраторами баз данных для мониторинга и оптимизации). Все рассматриваемые системы являются SQL Server 2008 R2, если это имеет значение.
У меня есть базовый запрос, но я застрял при попытке предоставить фактические имена индексов. Насколько мне известно, эта информация содержится в представлении sys.indexes каждого пользователя. Моя конкретная проблема - попытка ссылаться на это представление программно из хранимой процедуры другой базы данных.
Чтобы проиллюстрировать это, это часть запроса:
FROM sys.dm_db_index_physical_stats(@db_id,NULL,NULL,NULL,NULL) p
INNER JOIN sys.indexes b ON p.[object_id] = b.[object_id]
AND p.index_id = b.index_id
AND b.index_id != 0
Запрос работает нормально при выполнении из базы данных, идентифицируемой @db_id, потому что он использует правильное представление sys.indexes. Однако, если я попытаюсь вызвать это из базы данных DBA, все получится нулевым, поскольку представление sys.indexes предназначено для неверной базы данных.
В более общем плане, я должен быть в состоянии сделать что-то вроде этого:
DECLARE @db_name NVARCHAR(255) = 'my_database';
SELECT * FROM @db_name + '.sys.indexes';
или же
USE @db_name;
Я пытался переключать базы данных или ссылаться на другие базы данных, используя комбинации конкатенации строк и функций OBJECT_NAME / OBJECT_ID / DB_ID, но ничего не работает. Я был бы признателен за любые идеи, которые могут возникнуть у сообщества, но подозреваю, что мне придется переоснащать эту хранимую процедуру, чтобы размещать ее в каждой отдельной базе данных.
Спасибо заранее за любые предложения.
источник
Ответы:
Динамический SQL пригодится для этих типов административных задач. Вот фрагмент хранимой процедуры, которую я написал, которая не только получает уровни дефрагментации, но также генерирует код для выполнения дефрагментации:
источник
Альтернативой динамическому SQL является SQLCMD , который можно вызвать из командной строки, шага задания агента, командлета Invoke-Sqlcmd Powershell или включить в SSMS . Ваш пример в синтаксисе SQLCMD будет:
Режим SQLCMD - одна из тех функций, о которых я хотел бы знать раньше. Удобно во многих ситуациях.
источник
Обычно сложно сослаться на один набор таблиц из процедуры, содержащейся в другой БД. Если вы устанавливаете свою процедуру в Master как системную процедуру, то ее можно использовать в других контекстах БД, не пытаясь сослаться на себя.
Я думаю, что: если ваша процедура начинается с 'sp_', то она становится универсально видимой, и если вы определяете ее в схеме 'sys.sp_%', то она может использоваться в других контекстах БД.
Это обеспечило бы альтернативный способ работы в нескольких БД без необходимости динамического подключения имени_БД.
источник