【问题标题】:Add non-nullable columns to an existing table in SQL server?将不可为空的列添加到 SQL Server 中的现有表?
【发布时间】:2010-02-15 19:52:24
【问题描述】:

我已经有一个包含数据的表。我需要更改表以添加两个不为空的新列。如何在不丢失任何现有数据的情况下做到这一点?


这是我尝试过的(通过右键单击表格并选择设计):

  1. 添加了新列 'EmpFlag' (bit, null), 'CreatedDate' (datetime, 空)

  2. 更新了表中的“EmpFlag”列,使其具有一些有效值。 (只是想在一个领域工作,所以我没有更新“CreatedDate”字段)

  3. 现在右键单击表格,设计,并使其不为空。

当我尝试保存时,出现了这个错误信息:

不允许保存更改。 您所做的更改需要 以下表格将被删除并重新创建。

【问题讨论】:

  • 我认为这是 SSMS 设计工具的限制。尝试使用 SQL 语句执行此操作:“alter table tablename alter column EmpFlag bit not null”。只需使用它运行一个新查询,并将表名更改为真实名称。
  • 这与您所做更改的细节无关,而是反映了 SSMS 中的新默认行为 - 以防止人们在不知不觉中对大型生产表进行灾难性更改,这实际上会使它们脱机复制数据和重新填充表所需的时间。您可以关闭此选项工具 > 选项 > 设计器 > 表 + DB 设计器 > 防止保存更改...(取消选中此选项)。但是,对生产表进行这些更改时要非常小心。

标签: sql sql-server database


【解决方案1】:

您只需在新列中设置一个默认值,然后您就可以添加它们。

alter table table_name
    add column_name datetime not null
       constraint DF_Default_Object_Name default (getdate())

或者这个用于 varchar 字段。

alter table table_name
    add column_name varchar(10) not null
       constraint DF_Default_Object_Name default ('A')

添加列后,如果不需要,也可以删除默认值。

alter table table_name
    drop constraint DF_Default_Object_Name

【讨论】:

  • 请注意,如果您有 100% 的填充因子(默认值),那么像这样向所有行添加数据会导致大量页面拆分。这是很多 I/O,我相信这是一个阻塞操作。这在一个中等小的表上很好,但如果你有一个大而高吞吐量的表,它基本上是一个离线操作。据我所知,作为“在线”操作执行此操作的唯一方法是创建一个具有所需结构的新表;将数据与触发器和批处理操作合并;最后在单个事务中将新表交换到位(同义词效果很好)
  • 这个答案对我来说很好,但后来我意识到我可以在 SSMS 的设计表屏幕中完成完全相同的操作 - 添加一个不可为空的列,并在列属性中设置一个默认值或绑定,然后保存更改,如有必要,之后删除默认值或绑定
  • 多年来我一直在为此苦苦挣扎,并且总是编写 SQL 代码来重新创建表并填充数据。我不知道它是如此简单。我生命中的许多小时都被浪费了:-@
【解决方案2】:

如果您不想在列上设置默认值,您可以:

  1. 将新列创建为 NULLable
  2. 适当更新现有数据
  3. 添加 NOT NULL 约束

【讨论】:

  • 总的来说我同意,但这取决于场景。如果要添加 CreatedDate 和 ModifiedDate 之类的列,则可以应用默认值,然后根据需要返回并调整旧数据,那么您不必担心 2 到 2 之间的任何停机时间(或滑入的新行) 3. 在标准默认值有意义的情况下,这使您可以灵活地不同步所有尚不知道新列的代码。
  • 这对第 3 步很有用 - Altering a column: null to not null
【解决方案3】:

可以在 GUI 中添加具有默认值的新 NOT NULL 列,如下所示。将现有的更改为 NOT NULL 似乎是另一回事。我得到了和你一样的信息。一种选择是使用默认值创建一个新的 NOT NULL 列来替换旧列,然后将旧列数据复制到新列数据中。

  1. 将表格放入设计视图(右键单击表格->选择设计)
  2. 添加列,选择数据类型
  3. 取消选中 Allow Nulls 并设置 Default Value 或 Binding = 您的默认值,如下所示

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-12
    • 2010-09-10
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    相关资源
    最近更新 更多