我正在编写一个存储过程,它将数据库名称作为参数并返回该数据库索引及其碎片级别的表。这个存储过程将存在于我们的 DBA 数据库(包含 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
Run Code Online (Sandbox Code Playgroud)
当从@db_id 标识的数据库执行时,查询工作正常,因为它使用了正确的 sys.indexes 视图。但是,如果我尝试从 DBA 数据库中调用它,则所有结果都为空,因为 sys.indexes 视图用于错误的数据库。
更笼统地说,我需要能够做这样的事情:
DECLARE @db_name NVARCHAR(255) = 'my_database';
SELECT * FROM @db_name + '.sys.indexes';
Run Code Online (Sandbox Code Playgroud)
或者
USE @db_name;
Run Code Online (Sandbox Code Playgroud)
我尝试使用字符串连接和 OBJECT_NAME/OBJECT_ID/DB_ID 函数的组合来切换数据库或引用其他数据库,但似乎没有任何效果。我很感激社区可能有的任何想法,但我怀疑我将不得不重新调整这个存储过程以驻留在每个单独的数据库中。
在此先感谢您的任何建议。
dat*_*god 10
动态 SQL 对于这些类型的管理任务非常有用。这是我编写的存储过程的一个片段,它不仅可以获取碎片整理级别,还可以生成进行碎片整理的代码:
select @SQL =
'
select getdate(),
''' + @@ServerName + ''',
''' + @DatabaseName + ''',
so.Name,
si.Name,
db_id(''' + @DatabaseName + '''),
ips.object_id,
ips.index_id,
ips.index_type_desc,
ips.alloc_unit_type_desc,
ips.index_depth,
ips.avg_fragmentation_in_percent,
ips.fragment_count,
avg_fragment_size_in_pages,
ips.page_count,
ips.record_count,
case
when ips.index_id = 0 then ''alter table [' + @DatabaseName + '].'' + ss.name + ''.['' + so.name + ''] rebuild with (online = on)''
else ''alter index '' + si.name + '' on [' + @DatabaseName + '].'' + ss.name + ''.['' + so.name + ''] rebuild with (online = on)''
end
from sys.dm_db_index_physical_stats(db_id(''' + @DatabaseName + '''),null,null,null, ''' + @SampleMode + ''') ips
join [' + @DatabaseName + '].sys.objects so on so.object_id = ips.object_id
join [' + @DatabaseName + '].sys.schemas ss on ss.schema_id = so.schema_id
join [' + @DatabaseName + '].sys.indexes si on si.object_id = ips.object_id
and si.index_id = ips.index_id
order by so.Name, ips.index_id
'
exec (@SQL)
Run Code Online (Sandbox Code Playgroud)
动态 SQL 的替代方案是SQLCMD,它可以从命令行、代理作业步骤、Invoke-Sqlcmd Powershell cmdlet调用或在SSMS 中启用。您在 SQLCMD 语法中的示例是:
:SETVAR DatabaseName MyDatabase
SELECT * FROM $(DatabaseName).sys.indexes;
Run Code Online (Sandbox Code Playgroud)
SQLCMD 模式是我希望我早些知道的功能之一。在很多情况下都很方便。