Сохраните индексы SQL при изменении типа данных столбца

Вам будет нужна некоторая абстрактная фабрика одного вида или другого для перекладывания ответственности на:

interface Factory<E> {
    E create();
}

class SomeContainer<E> {
    private final Factory<E> factory;
    SomeContainer(Factory<E> factory) {
        this.factory = factory;
    }
    E createContents() {
        return factory.create();
    }
}
18
задан Phillip Benages 11 August 2009 в 03:45
поделиться

3 ответа

Вы не можете изменить тип данных с smalldatetime на datetime с указанными индексами, уникальными ограничениями, ограничениями внешнего ключа или проверочными ограничениями. Вам придется отбросить их все, прежде чем менять тип. Затем:

alter table T alter column TestDate datetime not null

Затем воссоздайте ограничения и индексы, которые все еще применяются.


Некоторые различные подходы к генерации отбрасывания и создания:

1) Если вы дали явные имена всем индексам и ограничениям, то ваш установщик может запустить статический сценарий в каждой среде (разработка, тестирование, приемочное тестирование пользователей, тестирование производительности и т. д., производство).

Чтобы сгенерировать этот явный сценарий, вы можете: a) Используйте SSMS (или SQL Server 2000, менеджер предприятия) для создания сценария операторов create и drop. б) Работайте из репозитория исходного кода, чтобы обнаружить имена и определения зависимых объектов и собрать соответствующий статический сценарий. c) Попытка запустить оператор alter. Посмотрите, на чем это не удается. Найдите определения и вручную напишите каплю и создайте. (Лично это было бы хорошо для записи перетаскивания, но не для создания.)

2) Если вы не указали явные имена для всех индексов и ограничений, то вашему установщику придется запросить словарь данных для подходящие имена и использование динамического SQL для запуска отбрасывания в правильном порядке перед оператором alter column, а затем создает в правильном порядке после alter column.

Это будет проще, если вы знаете, что есть без ограничений, только индексы.

Могут быть инструменты или библиотеки, которые уже знают, как это сделать.

Кроме того, если это пакетное приложение, вы не можете быть уверены, что локальные администраторы баз данных не добавили индексы.

ПРИМЕЧАНИЕ. Если есть уникальное ограничение,

14
ответ дан 30 November 2019 в 08:21
поделиться

Если вы просто меняете размер, индекс все равно останется в таблице.

Если вы меняете тип данных, вы получите сообщение об ошибке, в котором говорится, что объекты зависят от столбец, который вы пытаетесь изменить, и поэтому вы не сможете его изменить.

Вы можете создать скрипт для рассматриваемых индексов вручную или с помощью скрипта. В SSMS щелкните таблицу правой кнопкой мыши и создайте сценарий для рассматриваемого объекта.

Если вам нужен программный индексный скрипт, вот хранимая процедура, которую я использовал, которую я получил от моего бывшего коллеги.

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
9
ответ дан 30 November 2019 в 08:21
поделиться

РЕДАКТИРОВАТЬ : Это зависит от исходного и измененного типа данных. Если вы попытаетесь изменить столбец с varchar на nvarchar, это не удастся. Принимая во внимание, что если вы измените столбец с varchar (16) на varchar (32), это будет успешным.

--Disable Index
ALTER INDEX MyIndex ON MyTable DISABLE
GO

-- Change column datatype

--Enable Index
ALTER INDEX MyIndex ON MyTable REBUILD
GO

Если вы измените тип столбца, тогда все индексы, которые используют этот столбец, придется перестроить.

Но если у вас нет огромных объемов данных (или вы не работаете круглосуточно и без выходных), восстановление индексов не составит большого труда. Просто запланируйте перерыв на техническое обслуживание.

4
ответ дан 30 November 2019 в 08:21
поделиться