Change a Primary Key from Nonclustered to Clustered

前端 未结 3 594
闹比i
闹比i 2020-12-23 12:02

Suppose I have an SQL Server 2005 table, TableX, with 2 indexes on it:

PK_TableX = PRIMARY KEY NONCLUSTERED on FieldA
IX_TableX_FieldB = CLUSTERED on Fiel

相关标签:
3条回答
  • 2020-12-23 12:16

    Here's a shortcut to overwrite the original key:

    CREATE UNIQUE CLUSTERED INDEX [pk_name] ON [table_name]([id])
    WITH DROP_EXISTING
    

    And as mentioned in other answers you will still need to drop/re-add foreign constraints if present.

    0 讨论(0)
  • 2020-12-23 12:18

    I know this is old but this will script out all the FK drops, the pk drop, the pk recreate, the FK recreates. Replace MYTABLE with your table name.

       IF  EXISTS (SELECT * FROM sys.tables WHERE object_id = OBJECT_ID(N'[dbo].[FKAgainstTableList]'))
    BEGIN 
        DROP TABLE FKAgainstTableList
    END
    --CREATE TABLE FKAgainstTableList (ForeignKey VARCHAR(30),[Table] VARCHAR(30))
    DECLARE @PKTableName VARCHAR(100), 
            @PKName varchar(100),
            @FKName varchar(100),
            @sql varchar(max),
            @PKcolumnName varchar(30),
            @table VARCHAR(100),
            @FKColumnName VARCHAR(100), 
            @parentColumnNumber int
    SET @PKTableName = 'MYTABLE'
    set @PKName = (SELECT name FROM sys.indexes WHERE OBJECT_NAME(object_id) = @PKTableName AND is_primary_key = 1)
    set @PKcolumnName = (SELECT name FROM sys.columns WHERE OBJECT_NAME(object_id) = @PKTableName AND is_identity =1)
    PRINT @PKcolumnName
    
     SELECT  OBJECT_NAME(sys.foreign_key_columns.parent_object_id) [Table],sys.columns.name [FKColumnName],sys.foreign_keys.name [FKName] 
        INTO FKAgainstTableList
        FROM sys.foreign_keys INNER JOIN sys.foreign_key_columns 
        ON sys.foreign_keys.object_id = sys.foreign_key_columns.constraint_object_id
        INNER JOIN sys.columns ON sys.columns.object_id = sys.foreign_keys.parent_object_id AND sys.columns.column_id = sys.foreign_key_columns.parent_column_id
        WHERE OBJECT_NAME(sys.foreign_keys.referenced_object_id) = @PKTableName
    
    
    DECLARE table_cur1 CURSOR  FOR
        SELECT  * FROM FKAgainstTableList
    
        PRINT @sql
    
    -------------------------------Disable constraint on FK Tables
    OPEN table_cur1
    FETCH NEXT FROM table_cur1 INTO @table,@FKColumnName,@FKName
    WHILE   @@FETCH_STATUS = 0
        BEGIN
            SET @sql ='ALTER TABLE '+@table+' DROP CONSTRAINT '+ @FKName
            PRINT @sql
            FETCH NEXT FROM table_cur1 INTO @table,@FKColumnName,@FKName
        END
    CLOSE table_cur1
    DEALLOCATE table_cur1
    --------------------------------DROP AND recreate CLUSTERED pk
    IF  EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(@PKTableName) AND name = @PKName)
    BEGIN
        SET @sql = 'ALTER TABLE '+@PKTableName+' DROP CONSTRAINT '+ @PKName
        PRINT @sql
    
    END
    SET @sql = 'ALTER TABLE '+@PKTableName +' ADD  CONSTRAINT '+@PKName+' PRIMARY KEY CLUSTERED ('+@PKcolumnName+' ASC)
    WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 80) ON [PRIMARY]'
    PRINT(@sql)
    
    --------------------------------Enable FK constraints on FK tables.
    DECLARE table_cur2 CURSOR  FOR
        SELECT  * FROM FKAgainstTableList
    OPEN table_cur2
    FETCH NEXT FROM table_cur2 INTO @table,@FKColumnName,@FKName
    WHILE   @@FETCH_STATUS = 0
        BEGIN
            SET @sql = 'ALTER TABLE '+@table+' WITH NOCHECK ADD  CONSTRAINT  '+ @FKName+' FOREIGN KEY(['+@FKColumnName+'])
            REFERENCES ['+@PKTableName+'] (['+@PKcolumnName+'])'
            PRINT(@sql)
            SET @sql = 'ALTER TABLE '+@table+' CHECK CONSTRAINT  '+@FKName
            PRINT(@sql)
    
            FETCH NEXT FROM table_cur2 INTO @table,@FKColumnName,@FKName
    
             END
    CLOSE table_cur2
    DEALLOCATE table_cur2
    DROP TABLE FKAgainstTableList
    
    0 讨论(0)
  • 2020-12-23 12:28

    1) Drop the existing clustered index first (IX_TableX_FieldB):

       DROP INDEX TableX.IX_TableX_FieldB
    

    2) Create a (temporary) UNIQUE constraint on the unique fields referenced in the primary key

        ALTER TABLE TableX
        ADD CONSTRAINT UQ_TableX UNIQUE(FieldA)
    

    3) Drop the PRIMARY KEY

        ALTER TABLE TableX
        DROP CONSTRAINT PK_TableX
    

    4) Recreate the PRIMARY KEY as CLUSTERED

       ALTER TABLE TableX
       ADD CONSTRAINT PK_TableX PRIMARY KEY CLUSTERED(FieldA)
    

    5) Drop the temporary UNIQUE constraint

       ALTER TABLE TableX
       DROP CONSTRAINT UQ_TableX
    

    6) Add the IX_TableX_FieldB back on as NONCLUSTERED

       CREATE NONCLUSTERED INDEX IX_TableX_FieldB ON TableX(FieldB)
    
    0 讨论(0)
提交回复
热议问题