Preserve SQL Indexes While Altering Column Datatype

后端 未结 4 1985
既然无缘
既然无缘 2020-12-16 13:26

I have a smalldatetime column that I need to alter to be a datetime column. This is something that will be part of an install process, so it cannot be a manual procedure. Un

4条回答
  •  北海茫月
    2020-12-16 13:43

    If you are just changing the size, the Index will still remain on the table.

    If you are changing the data type, then you will get an error message stating that objects depend on the column that you are trying to change and therefore you will not be able to change it.

    You can script out the indexes in question manually or via script. In SSMS, right click the table and script out the object in question.

    If you want programatic index scripting, here is a stored proc that I have been using that I got from an ex colleague of mine.

    Drop Proc ScriptIndex
    GO
    Create Proc ScriptIndex
        @TableName      VarChar (Max),
        @IndexScript    VarChar (Max) OUTPUT
    AS
    
    -- Get all existing indexes, EXCEPT the primary keys
    DECLARE cIX CURSOR FOR
    SELECT OBJECT_NAME(SI.Object_ID), SI.Object_ID, SI.Name, SI.Index_ID
    FROM Sys.Indexes SI 
        LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC 
            ON SI.Name = TC.CONSTRAINT_NAME 
            AND OBJECT_NAME(SI.Object_ID) = TC.TABLE_NAME
    WHERE 1=1
        AND OBJECT_NAME(SI.Object_ID) = @TableName
        AND TC.CONSTRAINT_NAME IS NULL
        AND OBJECTPROPERTY(SI.Object_ID, 'IsUserTable') = 1
    ORDER BY OBJECT_NAME(SI.Object_ID), SI.Index_ID
    
    DECLARE @IxTable SYSNAME
    DECLARE @IxTableID INT
    DECLARE @IxName SYSNAME
    DECLARE @IxID INT
    
    -- Loop through all indexes
    OPEN cIX
    FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID
    WHILE (@@FETCH_STATUS = 0)
    BEGIN
       DECLARE @IXSQL NVARCHAR(4000) 
       DECLARE @PKSQL NVARCHAR(4000) 
       SET @PKSQL = ''
       SET @IXSQL = 'CREATE '
    
       -- Check if the index is unique
       IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsUnique') = 1)
          SET @IXSQL = @IXSQL + 'UNIQUE '
       -- Check if the index is clustered
       IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsClustered') = 1)
          SET @IXSQL = @IXSQL + 'CLUSTERED '
    
       SET @IXSQL = @IXSQL + 'INDEX ' + @IxName + ' ON ' + @IxTable + '('
    
       -- Get all columns of the index
       DECLARE cIxColumn CURSOR FOR 
          SELECT SC.Name
          FROM Sys.Index_Columns IC
             JOIN Sys.Columns SC ON IC.Object_ID = SC.Object_ID AND IC.Column_ID = SC.Column_ID
          WHERE IC.Object_ID = @IxTableID AND Index_ID = @IxID
          ORDER BY IC.Index_Column_ID
    
       DECLARE @IxColumn SYSNAME
       DECLARE @IxFirstColumn BIT SET @IxFirstColumn = 1
    
       -- Loop throug all columns of the index and append them to the CREATE statement
       OPEN cIxColumn
       FETCH NEXT FROM cIxColumn INTO @IxColumn
       WHILE (@@FETCH_STATUS = 0)
       BEGIN
          IF (@IxFirstColumn = 1)
             SET @IxFirstColumn = 0
          ELSE
             SET @IXSQL = @IXSQL + ', '
    
          SET @IXSQL = @IXSQL + @IxColumn
    
          FETCH NEXT FROM cIxColumn INTO @IxColumn
       END
       CLOSE cIxColumn
       DEALLOCATE cIxColumn
    
       SET @IXSQL = @IXSQL + ')'
       -- Print out the CREATE statement for the index
       PRINT @IXSQL
    
       FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID
    END
    
    CLOSE cIX
    DEALLOCATE cIX
    
    GO
    Declare @TableName VarChar (Max), @IndexScript VarChar (Max)
    
    Exec ScriptIndex 'Client', @IndexScript OUTPUT
    Print @IndexScript
    

提交回复
热议问题