我需要为我们整个生产环境的索引提出报告:
我在网上找到了以下脚本并根据我的要求对其进行了修改,并尝试使用游标(我也尝试过 sp_MSForEachDb)执行它以从实例中的所有数据库中获取结果。该脚本应显示特定数据库中的所有完全重复索引。
尽管我将查询用双引号括起来,但我总是收到太多错误。
如果我在没有循环的情况下运行脚本,它会正确返回结果。
请查看脚本和我在脚本下方遇到的错误。在过去的几天里,我一直在为此苦苦挣扎,并且在这里 和许多其他帖子上详尽地查看了在线内容,但无法解决这个问题。
我需要将电子邮件正文中的结果发送到我们所有服务器的分发列表。所以,如果有人对如何建立它有更好的想法,我将不胜感激。
脚本:
DECLARE @db_name AS nvarchar(max)
DECLARE c_db_names CURSOR FOR
SELECT name
FROM sys.databases
WHERE name NOT IN('master', 'model', 'msdb', 'tempdb') and state <> 1
OPEN c_db_names
FETCH c_db_names INTO @db_name
WHILE @@Fetch_Status = 0
BEGIN
IF OBJECT_ID('tempdb..#IndexTemp') IS NOT NULL DROP Table #IndexTemp --If exist drop the temp table.
EXEC('
Begin
USE ' + '[' + @db_name + ']' + '
;WITH CTE_INDEX_DATA AS (
SELECT
SCHEMA_DATA.name AS schema_name,
TABLE_DATA.name AS table_name,
INDEX_DATA.name AS index_name,
STUFF((SELECT '', '' + COLUMN_DATA_KEY_COLS.name + '' '' + CASE WHEN INDEX_COLUMN_DATA_KEY_COLS.is_descending_key = 1 THEN ''DESC'' ELSE ''ASC'' END -- Include column order (ASC / DESC)
FROM sys.tables AS T
INNER JOIN sys.indexes INDEX_DATA_KEY_COLS
ON T.object_id = INDEX_DATA_KEY_COLS.object_id
INNER JOIN sys.index_columns INDEX_COLUMN_DATA_KEY_COLS
ON INDEX_DATA_KEY_COLS.object_id = INDEX_COLUMN_DATA_KEY_COLS.object_id
AND INDEX_DATA_KEY_COLS.index_id = INDEX_COLUMN_DATA_KEY_COLS.index_id
INNER JOIN sys.columns COLUMN_DATA_KEY_COLS
ON T.object_id = COLUMN_DATA_KEY_COLS.object_id
AND INDEX_COLUMN_DATA_KEY_COLS.column_id = COLUMN_DATA_KEY_COLS.column_id
WHERE INDEX_DATA.object_id = INDEX_DATA_KEY_COLS.object_id
AND INDEX_DATA.index_id = INDEX_DATA_KEY_COLS.index_id
AND INDEX_COLUMN_DATA_KEY_COLS.is_included_column = 0
ORDER BY INDEX_COLUMN_DATA_KEY_COLS.key_ordinal
FOR XML PATH('')), 1, 2, '') AS key_column_list ,
STUFF(( SELECT '', '' + COLUMN_DATA_INC_COLS.name
FROM sys.tables AS T
INNER JOIN sys.indexes INDEX_DATA_INC_COLS
ON T.object_id = INDEX_DATA_INC_COLS.object_id
INNER JOIN sys.index_columns INDEX_COLUMN_DATA_INC_COLS
ON INDEX_DATA_INC_COLS.object_id = INDEX_COLUMN_DATA_INC_COLS.object_id
AND INDEX_DATA_INC_COLS.index_id = INDEX_COLUMN_DATA_INC_COLS.index_id
INNER JOIN sys.columns COLUMN_DATA_INC_COLS
ON T.object_id = COLUMN_DATA_INC_COLS.object_id
AND INDEX_COLUMN_DATA_INC_COLS.column_id = COLUMN_DATA_INC_COLS.column_id
WHERE INDEX_DATA.object_id = INDEX_DATA_INC_COLS.object_id
AND INDEX_DATA.index_id = INDEX_DATA_INC_COLS.index_id
AND INDEX_COLUMN_DATA_INC_COLS.is_included_column = 1
ORDER BY INDEX_COLUMN_DATA_INC_COLS.key_ordinal
FOR XML PATH('')), 1, 2, '') AS include_column_list,
INDEX_DATA.is_disabled -- Check if index is disabled before determining which dupe to drop (if applicable)
FROM sys.indexes INDEX_DATA
INNER JOIN sys.tables TABLE_DATA
ON TABLE_DATA.object_id = INDEX_DATA.object_id
INNER JOIN sys.schemas SCHEMA_DATA
ON SCHEMA_DATA.schema_id = TABLE_DATA.schema_id
WHERE TABLE_DATA.is_ms_shipped = 0
AND INDEX_DATA.type_desc IN (''NONCLUSTERED'', ''CLUSTERED'')
)
--Insert all records into a temp table #IndexTemp with appropriate filters:
SELECT * INTO #IndexTemp
FROM CTE_INDEX_DATA DUPE1
WHERE EXISTS
(SELECT * FROM CTE_INDEX_DATA DUPE2
WHERE DUPE1.schema_name = DUPE2.schema_name
AND DUPE1.table_name = DUPE2.table_name
AND DUPE1.key_column_list = DUPE2.key_column_list
AND ISNULL(DUPE1.include_column_list, '') = ISNULL(DUPE2.include_column_list, '')
AND DUPE1.index_name <> DUPE2.index_name)
AND INDEX_NAME NOT LIKE (''%PK%'')
--Return duplicate tbale_names only
SELECT * from #IndexTemp WHERE table_name IN
(SELECT table_name FROM #IndexTemp GROUP BY table_name HAVING COUNT(*) > 1)
ORDER BY table_name
END')
FETCH c_db_names INTO @db_name
END
CLOSE c_db_names
DEALLOCATE c_db_names
对于每个数据库,我都会收到以下错误:
消息 156,级别 15,状态 1,第 24 行
关键字“AS”附近的语法不正确。
消息 156,级别 15,状态 1,第 38 行
关键字“ORDER”附近的语法不正确。
消息 4145,级别 15,状态 1,第 59 行在
“AND”附近预期条件的上下文中指定的非布尔类型的表达式。
为什么不使用经过测试和理解的东西,比如sp_BlitzIndex ,而不是砍掉一个你不太了解的脚本来进行故障排除?
如果您运行
EXEC sp_BlitzIndex @Mode = 4, @GetAllDatabases = 1;
它,它将检查并诊断各种索引问题,超出您在 Internet™ 上找到的那个脚本中寻找的内容我同意Erik的观点,但在回答您的问题时,错误出现在 STUFF 和此处的引号中 AND ISNULL (DUPE1.include_column_list, '') = ISNULL (DUPE2.include_column_list, '')
您没有正确使用引号,请记住,当您混合文本时,所有的 '' 都必须像 '' ''