作为核对改变工作的一部分,我有一个需要被丢弃,然后重新创建索引(122)的列表。 我怎样才能重新建立,而不必去通过GUI和它脚本来查询窗口每次这些指标?
从这个脚本获得我的索引列表
WITH indexCTE AS
(
SELECT Table_Name, Column_Name, Collation_Name
FROM information_schema.columns
WHERE Collation_Name IS NOT NULL AND Collation_Name = 'Modern_Spanish_CI_AS'
),
indexCTE2 AS
(
SELECT i.Name [Index Name], OBJECT_NAME(i.object_ID) [Table Name], c.Name [Column Name]
FROM sys.indexes i
INNER JOIN sys.index_columns ic ON i.index_id = ic.index_id AND i.object_id = ic.object_id
INNER JOIN sys.columns c ON ic.column_id = c.column_id AND ic.object_id = c.OBJECT_ID
WHERE EXISTS (SELECT 1 FROM indexCTE t1 WHERE t1.Table_Name = OBJECT_NAME(i.object_ID) AND t1.Column_Name = c.Name)
) SELECT * FROM indexCTE2
正如你可能会说,我仍然是一个小DBA所以请耐心等待我!
谢谢!
你很接近,我会说 - 我想这一点,你可以验证,如果这对你的作品,并显示您预期的122个指数中重新创建?
更新 :新增的功能,以确定CLUSTERED与非聚集索引类型,并且包含的列添加到索引的定义。
WITH indexCTE AS
(
SELECT DISTINCT
i.index_id, i.name, i.object_id
FROM
sys.indexes i
INNER JOIN
sys.index_columns ic
ON i.index_id = ic.index_id AND i.object_id = ic.object_id
WHERE
EXISTS (SELECT * FROM sys.columns c
WHERE c.collation_name = 'Modern_Spanish_CI_AS'
AND c.column_id = ic.column_id AND c.object_id = ic.object_id)
),
indexCTE2 AS
(
SELECT
indexCTE.name 'IndexName',
OBJECT_NAME(indexCTE.object_ID) 'TableName',
CASE indexCTE.index_id
WHEN 1 THEN 'CLUSTERED'
ELSE 'NONCLUSTERED'
END AS 'IndexType',
(SELECT DISTINCT c.name + ','
FROM
sys.columns c
INNER JOIN
sys.index_columns ic
ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 0
WHERE
indexCTE.OBJECT_ID = ic.object_id
AND indexCTE.index_id = ic.index_id
FOR XML PATH('')
) ixcols,
ISNULL(
(SELECT DISTINCT c.name + ','
FROM
sys.columns c
INNER JOIN
sys.index_columns ic
ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 1
WHERE
indexCTE.OBJECT_ID = ic.object_id
AND indexCTE.index_id = ic.index_id
FOR XML PATH('')
), '') includedcols
FROM
indexCTE
)
SELECT
'CREATE ' + IndexType + ' INDEX ' + IndexName + ' ON ' + TableName +
'(' + SUBSTRING(ixcols, 1, LEN(ixcols)-1) +
CASE LEN(includedcols)
WHEN 0 THEN ')'
ELSE ') INCLUDE (' + SUBSTRING(includedcols, 1, LEN(includedcols)-1) + ')'
END
FROM
indexCTE2
ORDER BY
TableName, IndexName
你得到的CREATE INDEX
你要找的声明?
渣
Great script Marc.
The only thing I think it is missing is the ascending or descending order indicator on each column. I have amended your script to include a case statement for the indexed columns to add in ASC or DESC depending on the is_descending_key column of the sys.index_columns view.
WITH indexCTE AS
(
SELECT DISTINCT
i.index_id, i.name, i.object_id
FROM
sys.indexes i
INNER JOIN
sys.index_columns ic
ON i.index_id = ic.index_id AND i.object_id = ic.object_id
WHERE
EXISTS (SELECT * FROM sys.columns c
WHERE
c.collation_name = 'Modern_Spanish_CI_AS'
AND c.column_id = ic.column_id AND c.object_id = ic.object_id)
),
indexCTE2 AS
(
SELECT
indexCTE.name 'IndexName',
OBJECT_NAME(indexCTE.object_ID) 'TableName',
CASE indexCTE.index_id
WHEN 1 THEN 'CLUSTERED'
ELSE 'NONCLUSTERED'
END AS 'IndexType',
(SELECT CASE WHEN ic.is_descending_key = 1 THEN c.name + ' DESC ,'
ELSE c.name + ' ASC ,'
END
FROM
sys.columns c
INNER JOIN
sys.index_columns ic
ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 0
WHERE
indexCTE.OBJECT_ID = ic.object_id
AND indexCTE.index_id = ic.index_id
FOR XML PATH('')
) ixcols,
ISNULL(
(SELECT DISTINCT c.name + ','
FROM
sys.columns c
INNER JOIN
sys.index_columns ic
ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 1
WHERE
indexCTE.OBJECT_ID = ic.object_id
AND indexCTE.index_id = ic.index_id
FOR XML PATH('')
), '') includedcols
FROM
indexCTE
)
SELECT
'CREATE ' + IndexType + ' INDEX ' + IndexName + ' ON ' + TableName +
'(' + SUBSTRING(ixcols, 1, LEN(ixcols)-1) +
CASE LEN(includedcols)
WHEN 0 THEN ')'
ELSE ') INCLUDE (' + SUBSTRING(includedcols, 1, LEN(includedcols)-1) + ')'
END
FROM
indexCTE2
ORDER BY
TableName, IndexName
DECLARE @T_IndexInfo TABLE
(
IndID NVARCHAR(128),
ObjectID NVARCHAR(128),
ColID NVARCHAR(128),
IndexName NVARCHAR(128),
TableName NVARCHAR(128),
ColumnName NVARCHAR(128),
KeyNo NVARCHAR(128),
ColType NVARCHAR(128)
)
INSERT INTO @T_IndexInfo
SELECT I.IndID,
SO.ID AS 'ObjectID',
SK.ColID,
I.Name AS 'IndexName',
SO.Name AS 'TableName',
SC.Name AS 'ColumnName',
Sk.KeyNo,
CASE WHEN Sk.KeyNo = 0 THEN 'Include'
ELSE 'Normal'
END AS 'ColType'
FROM sys.sysindexes I
INNER JOIN sys.sysobjects SO ON SO.ID = I.ID
AND SO.xtype = 'U'
INNER JOIN sys.sysindexkeys SK ON SK.IndID = I.IndID
AND SO.ID = SK.ID
INNER JOIN sys.syscolumns SC ON SC.ID = SO.ID
AND SC.ColID = SK.ColID
WHERE I.IndID > 0
AND I.IndID < 255
AND ( I.Status & 64 ) = 0
-- AND ( I.status & 2048 ) <> 2048 /******** comment this if PK's also need to be recreated *****/
ORDER BY SO.Name,
I.Name
DECLARE @T_Final TABLE
(
TableName NVARCHAR(128),
IndexName NVARCHAR(128),
NormalColumns NVARCHAR(MAX),
IncludedColumns NVARCHAR(MAX)
)
INSERT INTO @T_Final
SELECT DISTINCT
TableName,
IndexName,
STUFF(( SELECT ',[' + ColumnName + ']'
FROM @T_IndexInfo
WHERE IndID = I.IndID
AND ObjectID = I.ObjectID
AND ColType = 'Normal'
ORDER BY KeyNo
FOR
XML PATH('')
), 1, 1, '') AS 'NormalColumns',
STUFF(( SELECT ',[' + ColumnName + ']'
FROM @T_IndexInfo
WHERE IndID = I.IndID
AND ObjectID = I.ObjectID
AND ColType = 'Include'
FOR
XML PATH('')
), 1, 1, '') AS 'IncludedColumns'
FROM @T_IndexInfo I;
WITH indexCTE AS
(
SELECT Table_Name, Column_Name --, Collation_Name
FROM information_schema.columns
WHERE Collation_Name IS NOT NULL AND Collation_Name = 'Modern_Spanish_CI_AS'
),
indexCTE2 AS
(
SELECT i.Name [Index Name], OBJECT_NAME(i.object_ID) [Table Name], c.Name [Column Name]
FROM sys.indexes i
INNER JOIN sys.index_columns ic ON i.index_id = ic.index_id AND i.object_id = ic.object_id
INNER JOIN sys.columns c ON ic.column_id = c.column_id AND ic.object_id = c.OBJECT_ID
WHERE EXISTS (SELECT 1 FROM indexCTE t1 WHERE t1.Table_Name = OBJECT_NAME(i.object_ID) AND t1.Column_Name = c.Name)
)
SELECT IndexName, TableName, NormalColumns, IncludedColumns
INTO #temp1
FROM @T_Final z INNER JOIN indexCTE2 x ON z.IndexName = x.[Index Name]
-- To generate CREATE INDEX SCRIPT
SELECT 'CREATE INDEX [' + IndexName + '] ON [' + TableName + '].('
+ NormalColumns + ')' + CASE WHEN IncludedColumns IS NULL THEN ''
ELSE ' INCLUDE (' + IncludedColumns + ')'
END AS 'CreateScript'
FROM #temp1
-- To generate DROP INDEX SCRIPT
SELECT 'DROP INDEX [' + TableName + '].[' + IndexName + ']' AS 'DropScript'
FROM #temp1
DROP TABLE#temp1中
这是一个有点题外话,但想到我会反正这建议:
如果你不想保持SQL Server Management Studio中运行脚本,你可以创建一个runmyscripts.bat文件包括类似:
@echo off
echo Execute Scripts...
sqlcmd -i C:\Scripts\myscript1.sql
sqlcmd -i C:\Scripts\myscript2.sql
echo Scripts Complete.
echo Press any button to exit.
pause