How can I drop all indexes in a SQL database with one command?

前端 未结 7 1416
温柔的废话
温柔的废话 2021-02-04 00:01

So, how can I drop all indexes in a SQL database with one command? I have this command that will get me all the 20 or so drop statements, but how can I run all of those drop s

相关标签:
7条回答
  • 2021-02-04 00:35
    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
    

    Modify conditions according to your needs

    If u want to delete PK constraints, you will get this message if you try to drop index:

    An explicit DROP INDEX is not allowed on index... It is being used for PRIMARY KEY constraint enforcement.

    Then, use this...

    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'
    
    0 讨论(0)
  • 2021-02-04 00:37

    this worked for me we skip sys indexes and for constraints

    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
    
    0 讨论(0)
  • 2021-02-04 00:41

    None of the answers quite suited my needs.

    I needed one that will also drop indexes that backup unique or primary constraints (except if these can't be dropped as they back up a foreign key)

    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);
    
    0 讨论(0)
  • 2021-02-04 00:42

    You're very close.

    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
    
    0 讨论(0)
  • 2021-02-04 00:48

    Minor improvements to the accepted answer that I had to make in my own case, mostly to account for schemas:

    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
    

    Also: In my case it couldn't run in one go because the script becomes longer than 4000 characters. The only way I could think of to deal with that was to put a "top 20" on the inner select and execute it multiple times.

    0 讨论(0)
  • 2021-02-04 00:55

    The "Final Draft" that OP posts as part of his question errors out if there are already zero indexes on any table in the DB. I needed to fix that.

    Also, I wanted more control over the process than dropping all indexes on all tables, so I wrote the following stored proc to do it one table at a time:

    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
    

    I cycle through the specific tables in my DB which I want to drop indexes on using a loop, and I drop the indexes by calling this proc with the table name, and recreate better ones right after. This way, only one table at a time has no indexes.

    The reason I do this and the number of tables I do it on would make your head spin, but I definitely needed a proc like this!

    0 讨论(0)
提交回复
热议问题