无法删除索引,因为它不是统计信息集合
Cannot DROP the index because it is not a statistics collection
我正在尝试在 Sql Server Management Studio 上执行此命令:
DROP STATISTICS dbo.TableName.StatsName
但是我收到了这个错误:
Cannot DROP the index because it is not a statistics collection.
此外,如果我尝试进入导航菜单上的 table "Statistics" 文件夹,并尝试使用上下文菜单删除,语音 drop 已禁用。
当我尝试在 sys.stats
table 中查找它时,我得到以下结果:
Auto_Created: 0
User_Created: 0
有没有办法去掉这种统计数据?
编辑
感谢 CR241 的回答和 Dan Guzman 的评论,我能够找到解决这个问题的方法。我想改变一个 nvarchar 列的长度,但不能这样做,因为它有一些限制。
我在很多数据库 table 上遇到了同样的问题。这是因为使用 Database Tuning Advisor 创建的索引和统计信息很多。
所以我创建了一个脚本来删除它们(理想情况是在更改所有列后删除和恢复)。
也许这对其他人有用:
GO
DECLARE selectIndexes CURSOR FOR
SELECT
QUOTENAME(SCHEMA_NAME(t.[schema_id]))
+ '.' + QUOTENAME(t.name)
+ '.' + QUOTENAME(i.name) as FullIndexName
FROM sys.indexes i
INNER JOIN sys.tables t ON i.[object_id] = t.[object_id]
INNER JOIN sys.stats s ON s.object_id = i.object_id and s.name = i.name
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc ON i.Name = tc.CONSTRAINT_NAME
AND OBJECT_NAME(i.Object_ID) = tc.TABLE_NAME
where QUOTENAME(i.name) like '__dta_%' and i.type_desc = 'NONCLUSTERED';
DECLARE @fullIndexName nvarchar(max);
DECLARE @sql NVARCHAR(max) = '';
OPEN selectIndexes
FETCH NEXT FROM selectIndexes INTO @fullIndexName
WHILE (@@FETCH_STATUS = 0)
BEGIN
set @sql = @sql+ 'DROP INDEX ' + @fullIndexName + CHAR(13) + CHAR(10);
FETCH NEXT FROM selectIndexes INTO @fullIndexName
END
CLOSE selectIndexes
DEALLOCATE selectIndexes
print @sql;
--exec sp_executesql @sql;
首先你应该删除索引,然后它的统计信息也会自动删除,它是用与索引相同的名称创建的。所以我认为您不需要手动删除统计信息。
SQL 服务器通过 sys.stats 即 user_created 跟踪用户创建的统计信息。这就是为什么在创建新索引时,为避免此错误,我们必须在实际索引创建代码之前添加以下 IF EXISTS() 代码。
这是一个例子:
IF EXISTS ( SELECT *
FROM sys.indexes
WHERE name = N'IX_TestTable_1'
AND object_id = OBJECT_ID(N'[dbo].[TestTable]') )
DROP INDEX [dbo].[TestTable].[IX_TestTable_1]
GO
IF EXISTS ( SELECT *
FROM sys.stats
WHERE name = N'IX_TestTable_1'
AND object_id = OBJECT_ID(N'[dbo].[TestTable]')
AND user_created = 1 )
DROP STATISTICS [dbo].[TestTable].[IX_TestTable_1]
GO
CREATE NONCLUSTERED INDEX IX_TestTable_1 ON TestTable(Col1)
必须记住,只能删除用户创建的统计信息。因此,如果我们只是通过名称检查统计信息的存在,它将 return 为真,但是当它尝试删除该统计信息时,它将给出以下错误。
Cannot DROP the index ‘[dbo].[TestTable].[IX_TestTable_1]’ because it is not a statistics collection.
请检查此以了解 sys.stats (Transact-SQL)
auto_created: Indicates whether the statistics were automatically
created by SQL Server.
0 = Statistics were not automatically created by SQL Server.
1 = Statistics were automatically created by SQL Server.
我正在尝试在 Sql Server Management Studio 上执行此命令:
DROP STATISTICS dbo.TableName.StatsName
但是我收到了这个错误:
Cannot DROP the index because it is not a statistics collection.
此外,如果我尝试进入导航菜单上的 table "Statistics" 文件夹,并尝试使用上下文菜单删除,语音 drop 已禁用。
当我尝试在 sys.stats
table 中查找它时,我得到以下结果:
Auto_Created: 0
User_Created: 0
有没有办法去掉这种统计数据?
编辑
感谢 CR241 的回答和 Dan Guzman 的评论,我能够找到解决这个问题的方法。我想改变一个 nvarchar 列的长度,但不能这样做,因为它有一些限制。 我在很多数据库 table 上遇到了同样的问题。这是因为使用 Database Tuning Advisor 创建的索引和统计信息很多。 所以我创建了一个脚本来删除它们(理想情况是在更改所有列后删除和恢复)。 也许这对其他人有用:
GO
DECLARE selectIndexes CURSOR FOR
SELECT
QUOTENAME(SCHEMA_NAME(t.[schema_id]))
+ '.' + QUOTENAME(t.name)
+ '.' + QUOTENAME(i.name) as FullIndexName
FROM sys.indexes i
INNER JOIN sys.tables t ON i.[object_id] = t.[object_id]
INNER JOIN sys.stats s ON s.object_id = i.object_id and s.name = i.name
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc ON i.Name = tc.CONSTRAINT_NAME
AND OBJECT_NAME(i.Object_ID) = tc.TABLE_NAME
where QUOTENAME(i.name) like '__dta_%' and i.type_desc = 'NONCLUSTERED';
DECLARE @fullIndexName nvarchar(max);
DECLARE @sql NVARCHAR(max) = '';
OPEN selectIndexes
FETCH NEXT FROM selectIndexes INTO @fullIndexName
WHILE (@@FETCH_STATUS = 0)
BEGIN
set @sql = @sql+ 'DROP INDEX ' + @fullIndexName + CHAR(13) + CHAR(10);
FETCH NEXT FROM selectIndexes INTO @fullIndexName
END
CLOSE selectIndexes
DEALLOCATE selectIndexes
print @sql;
--exec sp_executesql @sql;
首先你应该删除索引,然后它的统计信息也会自动删除,它是用与索引相同的名称创建的。所以我认为您不需要手动删除统计信息。
SQL 服务器通过 sys.stats 即 user_created 跟踪用户创建的统计信息。这就是为什么在创建新索引时,为避免此错误,我们必须在实际索引创建代码之前添加以下 IF EXISTS() 代码。
这是一个例子:
IF EXISTS ( SELECT *
FROM sys.indexes
WHERE name = N'IX_TestTable_1'
AND object_id = OBJECT_ID(N'[dbo].[TestTable]') )
DROP INDEX [dbo].[TestTable].[IX_TestTable_1]
GO
IF EXISTS ( SELECT *
FROM sys.stats
WHERE name = N'IX_TestTable_1'
AND object_id = OBJECT_ID(N'[dbo].[TestTable]')
AND user_created = 1 )
DROP STATISTICS [dbo].[TestTable].[IX_TestTable_1]
GO
CREATE NONCLUSTERED INDEX IX_TestTable_1 ON TestTable(Col1)
必须记住,只能删除用户创建的统计信息。因此,如果我们只是通过名称检查统计信息的存在,它将 return 为真,但是当它尝试删除该统计信息时,它将给出以下错误。
Cannot DROP the index ‘[dbo].[TestTable].[IX_TestTable_1]’ because it is not a statistics collection.
请检查此以了解 sys.stats (Transact-SQL)
auto_created: Indicates whether the statistics were automatically created by SQL Server.
0 = Statistics were not automatically created by SQL Server.
1 = Statistics were automatically created by SQL Server.