SQL Server + изменение типа столбца - PullRequest
2 голосов
/ 08 ноября 2011

У меня есть база данных SQL Server 2008.Эта база данных имеет столбец, который представляет «бит».Этот битовый флаг теперь должен быть int.Моя проблема в том, что в таблице уже много данных.Есть ли способ легко сделать это преобразование?Учитывая, что я использую больший тип данных, я не вижу проблемы.Однако проблема заключается в содержащих данных.Как мне сопоставить мои битовые поля с соответствующими значениями типа int при изменении типа столбца.

Спасибо,

Ответы [ 3 ]

10 голосов
/ 08 ноября 2011

как это

ALTER TABLE TableName ALTER COLUMN ColumneName int
GO

измените TableName на имя вашей таблицы, а ColumneName на имя вашей колонки

см. Также: При изменении типов данных столбца используйте ALTER TABLE TableName ALTER Синтаксис столбца, не удаляйте и не создавайте заново столбец

2 голосов
/ 09 ноября 2011

SQLMenace имеет правильный ответ.

Если таблица просто огромна, то изменение может занять некоторое время и может блокировать в течение длительного времени.Если это так, и ваша база данных не может терпеть длительное время простоя для этой таблицы (возможно, это 24-часовой OLTP?), Я предлагаю сделать что-то вроде этого:

--Add a new temporary column to store the changed value.
ALTER TABLE dbo.TableName ADD NewColumnName int NULL;
CREATE NONCLUSTERED INDEX IX_TableName_NewColumnName ON dbo.TableName (NewColumName)
   INCLUDE (ColumnName); -- the include only works on SQL 2008 and up
-- This index may help or hurt performance, I'm not sure... :)

-- Update the table in batches of 10000 at a time
WHILE 1 = 1 BEGIN 
   UPDATE X -- Updating a derived table only works on SQL 2005 and up
   SET X.NewColumnName = ColumnName
   FROM (
      SELECT TOP 10000 * FROM dbo.TableName WHERE NewColumnName IS NULL
   ) X;
   IF @@RowCount = 0 BREAK;
END;

ALTER TABLE dbo.TableName ALTER COLUMN NewColumnName int NOT NULL;

BEGIN TRAN; -- now do as *little* work as possible in this blocking transaction
UPDATE T -- catch any updates that happened after we touched the row
SET T.NewColumnName = T.ColumnName
FROM dbo.TableName T WITH (TABLOCKX, HOLDLOCK)
WHERE T.NewColumnName <> T.ColumnName;
-- The lock hints ensure everyone is blocked until we do the switcheroo

EXEC sp_rename 'TableName.ColumName', 'OldColumName';
EXEC sp_rename 'TableName.NewColumnName', 'ColumName';
COMMIT TRAN;

DROP INDEX dbo.TableName.IX_TableName_NewColumnName;    
ALTER TABLE dbo.TableName DROP COLUMN OldColumnName;

Мой сценарий не проверен... может быть, это хорошая идея, чтобы проверить это в первую очередь.:)

Выполнение обновления в пакетном режиме сохраняет размер транзакции небольшим, предотвращает чрезмерное использование базы данных tempdb, рост объема транзакций и длительные блокировки (таблица может использоваться другими клиентами между циклами обновления).10k часто - хороший размер, но иногда могут потребоваться меньшие числа в зависимости от того, сколько времени это займет.В идеале вы должны выбрать размер, который бы занимал значительную часть памяти, но не выдавливал кого-либо другого и использовал мало или вообще не использовал tempdb.С помощью такой циклической стратегии я сократил многочасовые обновления для огромных таблиц до нескольких минут (и что более важно, неблокирующих минут).

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

CREATE NONCLUSTERED INDEX IX_TableName_NewColumnName_Null ON dbo.TableName (NewColumName)
WHERE NewColumnName IS NULL; -- SQL 2008 and up only

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

1 голос
/ 08 ноября 2011

У меня есть длинная статья на эту тему в Столбцы таблицы SQL Server под капотом .Делайте так, как предлагает SQLMenace, используя ALTER TABLE ... ALTER COLUMN.Поскольку это изменение увеличивает размер столбца, изменение не может быть только метаданными, ему нужно будет выполнить операцию с размером данных (обновить каждую строку).Но это будет прозрачно для вас (читайте в связанной статье для более подробной информации).Однако вы должны быть готовы к обработке потенциально большой транзакции по мере обновления каждой строки, поэтому убедитесь, что у вас достаточно места для журнала, чтобы не исчерпать пространство журнала из-за большой транзакции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...