如何解决表和视图索引比较和CTE迭代
作为练习,我写了一个小脚本
- 查找给定表上的索引和列
- 查找依赖于该表的索引视图(及其列)
- 将视图上的索引与表上的索引进行比较,以查看是否有任何索引视图相同。
这第三步给我带来了问题。我似乎无法理解进行迭代和比较。正在考虑使用 CTE 来比较每个索引列,但结果不正确。任何帮助都是最有帮助的。
DECLARE @table_name VARCHAR(1000)
SET @table_name = 'dbo.tableName'
DROP TABLE IF EXISTS tempdb.dbo.#tmp_TableIndexesAndColumns; --
DROP TABLE IF EXISTS tempdb.dbo.#tmp_ViewsIndexesAndColumns;
--------------------------------------------------------
-- qTable - Get Table Indexes and their Columns
--------------------------------------------------------
CREATE TABLE #tmp_TableIndexesAndColumns
(
tmpID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,table_schema_id INT NOT NULL,table_schema VARCHAR (5) NOT NULL,table_id INT NOT NULL,table_name VARCHAR(1000) NOT NULL,table_index_id INT NOT NULL,table_index_name VARCHAR(1000) NOT NULL,table_index_type_id INT NOT NULL,table_index_type VARCHAR(50) NOT NULL,table_is_unique BIT NOT NULL,table_column_id INT NOT NULL,table_column_name VARCHAR(1000) NOT NULL,table_is_included BIT NOT NULL
);
INSERT INTO #tmp_TableIndexesAndColumns
SELECT
obj_table.schema_id,SCHEMA_NAME(obj_table.schema_id),obj_table.object_id,obj_table.[name] AS table_name,i.index_id index_id,i.[name] AS index_name,i.[type] AS index_type_id,CASE
WHEN i.[type] = 1 THEN
'Clustered index'
WHEN i.[type] = 2 THEN
'Nonclustered unique index'
WHEN i.[type] = 3 THEN
'XML index'
WHEN i.[type] = 4 THEN
'Spatial index'
WHEN i.[type] = 5 THEN
'Clustered columnstore index'
WHEN i.[type] = 6 THEN
'Nonclustered columnstore index'
WHEN i.[type] = 7 THEN
'Nonclustered hash index'
ELSE
''
END AS index_type,i.is_unique,col_idx.column_id,col_idx.[name] AS [column_name],col_idx.is_included_column
FROM sys.objects obj_table
INNER JOIN sys.indexes i
ON obj_table.object_id = i.object_id
CROSS APPLY
(
SELECT col.column_id,col.[name],ic.is_included_column
FROM sys.index_columns ic
INNER JOIN sys.columns col
ON ic.object_id = col.object_id
AND ic.column_id = col.column_id
WHERE ic.object_id = obj_table.object_id
AND ic.index_id = i.index_id
) col_idx
WHERE obj_table.object_id = OBJECT_ID(@table_name)
AND obj_table.is_ms_shipped <> 1
AND i.index_id > 0
ORDER BY i.index_id,col_idx.column_id ;
--------------------------------------------------------
-- qTable - Get View Indexes and their Columns
-- (Views that Referencing Our Table)
--------------------------------------------------------
CREATE TABLE #tmp_ViewsIndexesAndColumns
(
tmpID INT IDENTITY(1,view_schema_id INT NOT NULL,view_schema VARCHAR (5) NOT NULL,view_id INT NOT NULL,view_name VARCHAR(1000) NOT NULL,view_index_id INT NOT NULL,view_index_name VARCHAR(1000) NOT NULL,view_index_type_id INT NOT NULL,view_index_type VARCHAR(50) NOT NULL,view_is_unique BIT NOT NULL,referenced_column_id INT NOT NULL,referenced_column_name VARCHAR(1000) NOT NULL,referenced_is_included BIT NOT NULL
);
INSERT INTO #tmp_ViewsIndexesAndColumns
SELECT disTINCT
obj_view.schema_id,SCHEMA_NAME(obj_view.schema_id) AS view_schema,obj_view.object_id,obj_view.[name] AS view_name,i.index_id,col_idx.is_included_column
FROM sys.objects obj_table
JOIN sys.sql_expression_dependencies sed
on sed.referenced_id = obj_table.object_id
join sys.objects obj_view
on sed.referencing_id = obj_view.object_id
JOIN sys.indexes i
ON obj_view.object_id = i.object_id
CROSS APPLY
(
SELECT col.column_id,ic.is_included_column
FROM sys.index_columns ic
INNER JOIN sys.columns col
ON ic.object_id = col.object_id
AND ic.column_id = col.column_id
WHERE ic.object_id = obj_view.object_id
AND ic.index_id = i.index_id
) col_idx
WHERE obj_table.object_id = OBJECT_ID(@table_name)
AND obj_view.is_ms_shipped <> 1
AND i.index_id > 0
ORDER BY obj_view.object_id,i.[name];
--------------------------------------------------------
-- qCompare - Find Identical View and Table Indexes
--------------------------------------------------------
WITH cte_table_index AS
(SELECT
ROW_NUMBER() OVER (PARTITION BY tbl.table_index_id ORDER BY tbl.table_column_id) group_id,tbl.table_index_id,tbl.table_column_id
FROM #tmp_TableIndexesAndColumns tbl
UNION ALL
SELECT
ROW_NUMBER() OVER (PARTITION BY tbl.table_index_id ORDER BY tbl.table_column_id) group_id,vw.view_index_id,vw.referenced_column_id
FROM #tmp_TableIndexesAndColumns tbl
INNER JOIN #tmp_ViewsIndexesAndColumns vw
ON tbl.table_column_id = vw.referenced_column_id)
SELECT * FROM cte_table_index
DROP TABLE IF EXISTS tempdb.dbo.#tmp_TableIndexesAndColumns;
DROP TABLE IF EXISTS tempdb.dbo.#tmp_ViewsIndexesAndColumns;
先谢谢你!
解决方法
这是我的尝试。
我们获取表的所有索引,匹配视图中的引用,连接表和视图的索引。
然后我们过滤如下:
两组索引列的全连接中不得存在任何内容。这个完全连接被过滤为只包含不匹配的索引列(内部 NOT EXISTS
只是对所有这些不同的东西进行可空比较的简写,这里没有 FROM
):
SELECT
obj_table.schema_id,SCHEMA_NAME(obj_table.schema_id),obj_table.object_id,obj_table.[name] AS table_name,iT.index_id index_id,iT.[name] AS index_name,iT.[type] AS index_type_id,iT.type_desc AS index_type,iT.is_unique,obj_view.schema_id,SCHEMA_NAME(obj_view.schema_id) AS view_schema,obj_view.object_id,obj_view.[name] AS view_name,iV.index_id index_id,iV.[name] AS index_name,iV.[type] AS index_type_id,iV.type_desc AS index_type,iV.is_unique
FROM sys.objects obj_table
JOIN sys.indexes iT
ON obj_table.object_id = iT.object_id
JOIN sys.sql_expression_dependencies sed
on sed.referenced_id = obj_table.object_id
JOIN sys.objects obj_view
on sed.referencing_id = obj_view.object_id
JOIN sys.indexes iV
ON obj_view.object_id = iV.object_id
WHERE NOT EXISTS (SELECT 1
FROM sys.index_columns icT
INNER JOIN sys.columns colT
ON icT.object_id = colT.object_id AND icT.column_id = colT.column_id
-- outer ref
AND icT.object_id = obj_table.object_id
AND icT.index_id = iT.index_id
FULL JOIN (sys.index_columns icV
INNER JOIN sys.columns colV
ON icV.object_id = colV.object_id AND icV.column_id = colV.column_id
-- outer ref
AND icV.object_id = obj_view.object_id
AND icV.index_id = iV.index_id
) ON icV.index_column_id = icT.index_column_id
WHERE NOT EXISTS (
SELECT
icT.index_column_id,icT.is_descending_key,icT.key_ordinal,colT.user_type_id,colT.max_length,colT.precision,colT.scale,colT.collation_name,colT.is_nullable
INTERSECT
SELECT
icV.index_column_id,icV.is_descending_key,icV.key_ordinal,colV.user_type_id,colV.max_length,colV.precision,colV.scale,colV.collation_name,colV.is_nullable
)
)
WHERE obj_table.object_id = OBJECT_ID(@table_name)
AND obj_table.is_ms_shipped <> 1
AND i.index_id > 0;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。