我有一个SQL Server 2008数据库。该数据库有一个代表“位”的列。这个位标志现在需要是一个int。我的问题是,表中已有很多数据。有没有办法轻松完成这种转换?考虑到我使用的是更大的数据类型,我没有看到问题。但问题是包含数据。在更改列类型时,如何将我的位字段映射到相应的int值。
谢谢,
答案 0 :(得分:10)
ALTER TABLE TableName ALTER COLUMN ColumneName int
GO
将表名更改为表的名称,将列名更改为列的名称
答案 1 :(得分:2)
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
另一方面,如果在更新新列数据之后添加原始非聚簇索引或者可能阻塞,则添加原始非聚簇索引可能需要更长时间。或者它可能不会花费太多时间。实验是有序的。
答案 2 :(得分:1)
我在SQL Server table columns under the hood有一篇关于这个主题的长篇文章。按照SQLMenace的建议,使用ALTER TABLE ... ALTER COLUMN
。由于此更改会增加列大小,因此更改不能仅限元数据,因此需要执行数据大小操作(更新每一行)。但这对您来说是透明的(阅读链接文章了解更多详情)。但是,随着每行更新的进行,您需要准备好处理可能很大的事务,因此请确保您有足够的日志空间,这样您就不会因为大事务而耗尽日志空间。