在数据库中添加新列的正确方法

Jac*_*ock 0 index source-control database-design sql-server table

当我们向现有表中添加新列时,正确的方法是什么?

例如,我已经有像 Foo1、Foo2、Bar1、Bar2 这样的列。现在我想添加一个名为 Foo3 的新列。

当我想添加具有相似名称的列时,标准方法是什么(如果是这样的话)?

我看到 2 个选择:

  1. 创建具有新结构的临时表,其中新列位于同名列的旁边,将数据从现有表复制到新表并删除现有表并重命名临时表。有点复杂的过程,但使数据库字段更具可读性。
  2. 最后添加新列。操作更简单。但是列名如果放在最后可能不会被清楚地理解。

为了获得一些参考,我们正在使用数据库项目来控制数据库更改,并为应用程序开发人员提供更好的 GUI 以进行数据库更改。我们使用某种 ORM 与数据库交互,因此没有人使用数据库对象名称查询数据库。

更新: 我在一些现有列上有几个索引。但是名称相似的列(包括我想添加的列)不属于任何索引。

Jos*_*ell 5

作为曾经尝试像这样将列放在一起的人,我强烈建议您选择选项 #2。

将列视觉上保持在一起(在 SSMS 列列表中/当您SELECT *从表格中时)的有争议的好处与选项 #1 的缺点相比绝对相形见绌。

随着表变大,执行这种“复制和替换”操作将花费越来越长的时间,并使用更多资源(I/O、内存、CPU)。

此外,您确实需要确保在复制和替换过程中不会丢失任何数据,因此必须使用对并发最不友好的隔离级别 ( SERIALIZABLE)。这意味着修改现有表的访问将被阻止,直到操作完成。因此,您可以将长时间的阻塞添加到缺点列表中。

SSDT 发布在重新排序这样的列时会自动使用这种代码(来自我关于主题的博客文章):

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;
Run Code Online (Sandbox Code Playgroud)

最重要的是,如果您手动执行此操作(而不是使用 SSDT 模式比较),那么很容易出错(将数据放入错误的列、复制/粘贴错误等)——尤其是在带有很多列。