Sql-Server
在數據庫中添加新列的正確方法
當我們將新列添加到現有表中時,正確的方法是什麼?
例如,我已經有像 Foo1、Foo2、Bar1、Bar2 這樣的列。現在我想添加一個名為 Foo3 的新列。
當我想添加具有相似名稱的列時,標準方法是什麼(如果是這樣的話)?
我看到 2 個選擇:
- 創建具有新結構的臨時表,其中新列位於具有相同名稱的列旁邊,將數據從現有表複製到新表並刪除現有表並重命名臨時表。有點複雜的過程,但使數據庫欄位更具可讀性。
- 最後添加新列。操作更簡單。但是,如果最後列名可能無法清楚地理解。
為了獲得一些參考,我們正在使用數據庫項目來控制數據庫更改,並為應用程序開發人員提供更好的 GUI 來進行數據庫更改。我們正在使用某種 ORM 與數據庫互動,因此沒有人使用數據庫對象名稱查詢數據庫。
更新: 我在一些現有列上有幾個索引。但是名稱相似的列(包括我要添加的列)不是任何索引的一部分。
作為曾經嘗試像這樣將列保持在一起的人,我強烈建議您使用選項#2。
將列視覺上保持在一起的有爭議的好處(在 SSMS 列列表中/當您
SELECT *
從表格中時)與選項 #1 的缺點相比絕對相形見絀。隨著表變得越來越大,執行此“複製和替換”操作將花費越來越長的時間,並使用更多資源(I/O、記憶體、CPU)。
此外,您確實需要確保在複製和替換期間不會失去任何數據,因此使用對並發最不友好的隔離級別 (
SERIALIZABLE
) 將是必要的。這意味著修改現有表的訪問將被阻止,直到操作完成。因此,您可以將長時間的阻塞添加到缺點列表中。SSDT publish 在重新排序這樣的列時會自動使用這種程式碼(來自我關於該主題的部落格文章):
BEGIN TRANSACTION; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET XACT_ABORT ON; CREATE TABLE [dbo].[tmp_ms_xx_Post] ( [Id] INT IDENTITY (1, 1) NOT NULL, [CommentCount] INT NULL, [PostType] VARCHAR (10) NOT NULL ); IF EXISTS (SELECT TOP 1 1 FROM [dbo].[Post]) BEGIN SET IDENTITY_INSERT [dbo].[tmp_ms_xx_Post] ON; INSERT INTO [dbo].[tmp_ms_xx_Post] ([Id], [PostType]) SELECT [Id], [PostType] FROM [dbo].[Post]; SET IDENTITY_INSERT [dbo].[tmp_ms_xx_Post] OFF; END DROP TABLE [dbo].[Post]; EXECUTE sp_rename N'[dbo].[tmp_ms_xx_Post]', N'Post'; COMMIT TRANSACTION; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
最重要的是,如果您手動執行此操作(而不是使用 SSDT 模式比較),那麼很容易出錯(將數據放入錯誤的列,複製/粘貼錯誤等) - 特別是在帶有很多列。