2011-11-08 79 views
2

我有一個SQL Server 2008數據庫。這個數據庫有一個表示「位」的列。這位標誌現在需要是一個int。我的問題是,表中已經有很多數據。有沒有辦法輕鬆完成此轉換?考慮到我使用更大的數據類型,我沒有看到問題。但是,問題是包含的數據。如何在更改列類型的同時將我的位字段映射到相應的int值。SQL Server +更改列類型

謝謝

回答

1

我有關於這個主題的長篇文章SQL Server table columns under the hood。按照SQLMenace的建議,使用ALTER TABLE ... ALTER COLUMN。由於此更改增加了列大小,所以更改不能僅爲元數據,它需要執行數據大小操作(每行更新一次)。但是這對你來說是透明的(閱讀鏈接文章獲取更多細節)。但是,隨着每行更新的進行,您需要準備好處理潛在的大事務,因此請確保您有足夠的日誌空間,以避免由於大事務而導致日誌空間不足。

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的使用情況,TRAN日誌增長,而長鎖(該表可以被其他客戶在每次更新循環之間使用)。 10k通常是一個很好的尺寸,但有時需要較小的數字,具體取決於需要多長時間。理想情況下,你會選擇使用大部分內存的大小,但不會擠出其他人,並使用很少或沒有tempdb。我已經用這種循環策略將幾個小時的更新對巨大的表減少了幾分鐘(更重要的是,非阻塞分鐘)。

注:對於那些與這一戰略的性能試驗,非聚集索引,我建議將幫助大部分腳本的交易部分中。對於一個簡單的巨大的表,不同的非聚集索引可以幫助:

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

在另一方面,如果加上它的更新新列的數據之後進行原非聚集索引可能需要更長的時間,或可能阻塞。或者它可能不需要太多時間。實驗是爲了。

相關問題