Sql-Server
動態 T-SQL 中的幫助錯誤消息
我需要為我們的整個生產環境提供索引報告:
我在網上找到了以下腳本並根據我的要求對其進行了修改,並嘗試使用游標執行它(我也嘗試過 sp_MSForEachDb)以從實例中的所有數據庫中獲取結果。該腳本應顯示特定數據庫中的所有 Exact Duplicate 索引。
儘管我已將查詢用雙引號括起來,但我不斷收到太多錯誤。
如果我在沒有循環的情況下執行腳本,它會正確返回結果。
請查看我在腳本下方遇到的腳本和錯誤。在過去的幾天裡,我一直在為此苦苦掙扎,並且在這里 和許多其他文章中詳盡地查看了線上資訊,但無法弄清楚這一點。
我需要將結果以電子郵件正文的形式發送到我們所有伺服器的分發列表。所以,如果有人對如何建立這個有更好的想法,我將不勝感激。
腳本:
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 行
在預期條件的上下文中指定的非布爾類型表達式,靠近“與”。
我同意Erik的觀點,但在回答你的問題時,錯誤出現在 STUFF 和此處的引號中 AND ISNULL (DUPE1.include_column_list, ‘’) = ISNULL (DUPE2.include_column_list, ‘’)
您沒有正確使用引號,請記住,當您混合文本時,所有的 ’’ 必須像 ’’ '’
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 ,--BAD quotation 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,--BAD quotation 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, '''') --BAD quotation 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