如何使用一个命令删除SQL数据库中的所有索引?

时间:2009-08-28 00:14:11

标签: sql sql-server tsql

那么,如何使用一个命令删除SQL数据库中的所有索引?我有这个命令可以获取所有20个左右的drop语句,但是如何从这个“结果集”中运行所有这些drop语句?

select * from vw_drop_idnex;

另一个给我相同列表的变体是:

SELECT  'DROP INDEX ' + ix.Name + ' ON ' + OBJECT_NAME(ID)  AS QUERYLIST
FROM  sysindexes ix
WHERE   ix.Name IS NOT null and ix.Name like '%pre_%'

我尝试做“exec(从vw_drop_idnex中选择cmd)”并且它不起作用。我正在寻找像for循环一样的东西并逐个运行查询。

-----------------------

在Rob Farleys的帮助下,剧本的最终草稿是:

declare @ltr nvarchar(1024);
SELECT @ltr = ( select 'alter table '+o.name+' drop constraint '+i.name+';'
  from sys.indexes i join sys.objects o on  i.object_id=o.object_id
  where o.type<>'S' and is_primary_key=1
  FOR xml path('') );
exec sp_executesql @ltr;

declare @qry nvarchar(1024);
select @qry = (select 'drop index '+o.name+'.'+i.name+';'
  from sys.indexes i join sys.objects o on  i.object_id=o.object_id
  where o.type<>'S' and is_primary_key<>1 and index_id>0
for xml path(''));
exec sp_executesql @qry

7 个答案:

答案 0 :(得分:25)

你非常接近。

declare @qry nvarchar(max);
select @qry = 
(SELECT  'DROP INDEX ' + ix.name + ' ON ' + OBJECT_NAME(ID) + '; '
FROM  sysindexes ix
WHERE   ix.Name IS NOT null and ix.Name like '%prefix_%'
for xml path(''));
exec sp_executesql @qry

答案 1 :(得分:6)

这对我有用 我们跳过sys索引和约束

declare @qry nvarchar(max);
select @qry = (

    select  'IF EXISTS(SELECT * FROM sys.indexes WHERE name='''+ i.name +''' AND object_id = OBJECT_ID(''['+s.name+'].['+o.name+']''))      drop index ['+i.name+'] ON ['+s.name+'].['+o.name+'];  '
    from sys.indexes i 
        inner join sys.objects o on  i.object_id=o.object_id
        inner join sys.schemas s on o.schema_id = s.schema_id
    where o.type<>'S' and is_primary_key<>1 and index_id>0
    and s.name!='sys' and s.name!='sys' and is_unique_constraint=0
for xml path(''));

exec sp_executesql @qry

答案 2 :(得分:5)

来自:Stephen Hill's Bloggie

DECLARE @indexName VARCHAR(128)
DECLARE @tableName VARCHAR(128)

DECLARE [indexes] CURSOR FOR

        SELECT          [sysindexes].[name] AS [Index],
                        [sysobjects].[name] AS [Table]

        FROM            [sysindexes]

        INNER JOIN      [sysobjects]
        ON              [sysindexes].[id] = [sysobjects].[id]

        WHERE           [sysindexes].[name] IS NOT NULL 
        AND             [sysobjects].[type] = 'U'
        --AND               [sysindexes].[indid] > 1

OPEN [indexes]

FETCH NEXT FROM [indexes] INTO @indexName, @tableName

WHILE @@FETCH_STATUS = 0
BEGIN
        --PRINT 'DROP INDEX [' + @indexName + '] ON [' + @tableName + ']'
        Exec ('DROP INDEX [' + @indexName + '] ON [' + @tableName + ']')

        FETCH NEXT FROM [indexes] INTO @indexName, @tableName
END

CLOSE           [indexes]
DEALLOCATE      [indexes]

GO

答案 3 :(得分:1)

对我在自己的情况下必须接受的答案进行了一些小的改进,主要是考虑到模式:

declare @qry nvarchar(4000);
select @qry = (select 'drop index ['+s.name+'].['+o.name+'].['+i.name+'];'
  from sys.indexes i join sys.objects o on i.object_id=o.object_id join sys.schemas s on o.schema_id=s.schema_id
  where o.type<>'S' and is_primary_key<>1 and index_id>0 and s.name<>'sys'
for xml path(''));
exec sp_executesql @qry

另外:在我的情况下,它无法一次性运行,因为脚本变得超过4000个字符。我能想到的唯一方法就是在内部选择上加上“前20名”并多次执行。

答案 4 :(得分:1)

如果数据库中任何表上的索引已经为零,则OP作为其问题的一部分发布的“最终草稿”会出错。我需要解决这个问题。

此外,与删除 all 表上的所有索引相比,我希望对过程进行更多控制,因此我编写了以下存储的proc来一次在一个表上进行操作:

CREATE PROCEDURE [dbo].[sp_DropAllIndexesOnTable]

@TableName varchar(1000)

AS
BEGIN
SET NOCOUNT ON;

   DECLARE @DropCommand1 nvarchar(4000)
   DECLARE @DropCommand2 nvarchar(4000)

--Create Temp Table to hold the names and table names of all Clustered Indexes
    SELECT o.name AS TableName, i.name AS IndexName
      INTO #AllClustered
      FROM sys.indexes i 
INNER JOIN sys.objects o ON i.object_id=o.object_id
     WHERE o.type <> 'S'
       AND is_primary_key = 1

--Create Temp Table to hold the names and table names of all NonClustered Indexes
    SELECT o.name AS TableName, i.name AS IndexName
      INTO #AllNonClustered
      FROM sys.indexes i 
INNER JOIN sys.objects o ON i.object_id=o.object_id
     WHERE o.type <> 'S'
       AND is_primary_key <> 1 
       AND index_id > 0

--Create DROP CONSTRAINT command for the Primary Key Constraint if there is one
    SELECT @DropCommand1 = ( SELECT 'ALTER TABLE dbo.['+ TableName +'] DROP CONSTRAINT ['+ IndexName +'];'
                               FROM #AllClustered
                              WHERE TableName = @TableName
                                FOR xml path('') ); 

--Create DROP INDEX command for the indexes on the table if there are any 
    SELECT @DropCommand2 = ( SELECT 'DROP INDEX [' + IndexName + '] ON dbo.['+ TableName +'];'
                               FROM #AllNonClustered
                              WHERE TableName = @TableName
                                FOR xml path('') );

        IF (@DropCommand1 IS NULL AND @DropCommand2 IS NULL) PRINT 'No action taken, zero indexes found on table ' + @TableName
        IF @DropCommand1 IS NOT NULL EXEC sp_executesql @DropCommand1
        IF @DropCommand2 IS NOT NULL EXEC sp_executesql @DropCommand2

DROP TABLE IF EXISTS #AllClustered
DROP TABLE IF EXISTS #AllNonClustered

END
GO

我循环遍历数据库中的特定表,希望使用循环删除索引,然后通过使用表名调用此proc来删除索引,然后立即重新创建更好的表。这样,一次只有一个表没有索引。

执行此操作的原因和执行该操作的表的数量会使您旋转,但我绝对需要这样的处理!

答案 5 :(得分:0)

这些答案都不适合我的需要。

我需要一个也会删除备份唯一或主要约束的索引(除非这些索引在备份外键时不能删除)

DECLARE @SqlScript NVARCHAR(MAX);


SELECT @SqlScript = 
(
SELECT 
'
BEGIN TRY
'+ CASE WHEN 1 IN (i.is_primary_key, i.is_unique_constraint) THEN
 '
 ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + '.' + QUOTENAME(t.name)  + ' DROP CONSTRAINT ' + QUOTENAME(i.name) + ';'
else
 '
 DROP INDEX ' + QUOTENAME(i.name)  + ' ON ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + '.' + QUOTENAME(t.name)
 END+'

END TRY
BEGIN CATCH
RAISERROR(''Could not drop %s on table %s'', 0,1, ' + QUOTENAME(i.name, '''') + ', ' + QUOTENAME(t.name, '''') + ')
END CATCH
'
FROM sys.indexes i
JOIN sys.tables t ON i.object_id = t.object_id
WHERE i.type_desc IN ('CLUSTERED', 'NONCLUSTERED' )
ORDER BY t.object_id, i.index_id DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)');

--Return script that will be run 
SELECT @SqlScript AS [processing-instruction(x)]
FOR XML PATH('');

EXEC (@SqlScript);

答案 6 :(得分:0)

SELECT  'DROP INDEX [' + IX.NAME + '] ON ' + OBJECT_NAME(IX.OBJECT_ID) + '; '
FROM  SYS.INDEXES IX
  JOIN SYS.OBJECTS O ON  IX.OBJECT_ID = O.OBJECT_ID
  INNER JOIN SYS.SCHEMAS S ON O.SCHEMA_ID = S.SCHEMA_ID
WHERE 
  IX.NAME IS NOT NULL 
  AND O.TYPE <> 'S' 
  AND IS_PRIMARY_KEY <> 1 
  AND INDEX_ID > 0
  AND S.NAME != 'SYS' AND S.NAME!= 'SYS' AND IS_UNIQUE_CONSTRAINT = 0

根据需要修改条件

如果您要删除PK约束,则尝试删除索引时会收到以下消息:

不允许在索引上使用显式的DROP INDEX。它正用于执行PRIMARY KEY约束。

然后,使用它...

SELECT 'ALTER TABLE [' + O.NAME + '] DROP CONSTRAINT  ' + IX.NAME + '; '
FROM  SYS.INDEXES IX
  JOIN SYS.OBJECTS O ON  IX.OBJECT_ID = O.OBJECT_ID
  INNER JOIN SYS.SCHEMAS S ON O.SCHEMA_ID = S.SCHEMA_ID
WHERE 
  IX.NAME IS NOT NULL 
  AND O.TYPE <> 'S' 
  AND INDEX_ID > 0
  AND S.NAME != 'SYS' AND S.NAME!= 'SYS'