【问题标题】:insert a NOT NULL column to an existing table在现有表中插入 NOT NULL 列
【发布时间】:2011-03-30 09:47:18
【问题描述】:

我试过了:

ALTER TABLE MY_TABLE 
ADD STAGE INT NOT NULL;

但它给出了这个错误信息:

ALTER TABLE 只允许添加可以包含空值或 指定了 DEFAULT 定义

【问题讨论】:

    标签: sql-server alter-table notnull


    【解决方案1】:

    作为一个选项,您可以最初创建 Null-able 列,然后使用有效的非空值更新表列,最后使用 ALTER 列设置 NOT NULL 约束:

    ALTER TABLE MY_TABLE ADD STAGE INT NULL
    GO
    UPDATE MY_TABLE SET <a valid not null values for your column>
    GO
    ALTER TABLE MY_TABLE ALTER COLUMN STAGE INT NOT NULL
    GO
    

    另一种选择是为您的列指定正确的默认值:

    ALTER TABLE MY_TABLE ADD STAGE INT NOT NULL DEFAULT '0'
    

    UPD:请注意,上面的答案包含GO,当您在 Microsoft SQL 服务器上运行此代码时,这是必须的。如果你想在 Oracle 或 MySQL 上执行相同的操作,你需要像这样使用分号;

    ALTER TABLE MY_TABLE ADD STAGE INT NULL;
    UPDATE MY_TABLE SET <a valid not null values for your column>;
    ALTER TABLE MY_TABLE ALTER COLUMN STAGE INT NOT NULL;
    

    【讨论】:

    • 如果您有可以手动输入字段的值,我个人更喜欢这里的第一种方式。这样您就不必担心创建和删除不需要的默认约束。
    • @acarlon - 我认为这已经达到了。您提到的危险update 语句在任何查询中都是有害的。在这里查看update 语句中是否有额外的列应该很简单。您通常一次只添加一两列。如果您碰巧在您的 update 语句中添加了一个不属于此处的额外列,在此示例中,那么您可能一开始就不应该负责数据。
    • ANDROID 使用 SQLite 的开发人员请注意,SQLite 不支持 ALTER COLUMN
    • 我以前从未见过GO,它似乎是not a part of the SQL specification,因此它可能会导致脚本不被支持它的工具之一执行失败。只用分号?我不建议传播微软标准,因为他们很少关心任何既定合理的标准,而是发明自己的标准只是为了自己发明。除此之外,有用的答案。
    • @Neon 感谢您的评论,但最初的问题是关于 MS SQL 服务器,这就是 GO 存在的原因。但我会在我的答案中添加一个关于它的注释。
    【解决方案2】:

    如果您不允许该列为 Null,则需要提供默认值来填充现有行。例如

    ALTER TABLE dbo.YourTbl ADD
        newcol int NOT NULL CONSTRAINT DF_YourTbl_newcol DEFAULT 0
    

    在企业版中,这是自 2012 年以来的 metadata only change

    【讨论】:

    • 您不需要,但这是一种选择。
    • @Matt 是的,你知道。如果表中根本没有任何行,并且给定条件“如果您不允许该列为 Null”,那么新列如何避免违反现有行的 NOT NULL 约束?
    • 另一种选择是将列添加为可为空,然后使用更新语句更新表中的每一行,然后将列更改为不可为空。这样,您就不会留下您可能不想要的 DEFAULT 约束。
    • @Matt - 这可能会慢很多,尤其是在具有默认值的方法仅作为元数据更改完成的情况下(即在企业版或 Azure SQL 数据库上默认具有运行时常量值)。如果不希望继续前进,很容易删除默认值。首先UPDATE 需要UPDATE 所有行然后更改为NOT NULL 也可以(有点令人惊讶)dba.stackexchange.com/questions/29522/…
    • 实际上我刚刚意识到这是对先前评论的延迟回复一年多。在这种情况下,您正在允许该列为NULL - 尽管只是暂时的。如果您想运行 ALTER TABLE ADD column NOT NULL 并且表中有行,您需要提供默认值
    【解决方案3】:

    错误信息描述性很强,试试:

    ALTER TABLE MyTable ADD Stage INT NOT NULL DEFAULT '-';
    

    【讨论】:

    • 默认部分的“减号”是什么意思?
    • 所有现有行和未指定“阶段”的未来行都将获得“-”作为值。
    【解决方案4】:

    Other SQL implementations have similar restrictions. 原因是添加列需要为该列添加值(逻辑上,即使不是物理上),默认为NULL。如果您不允许NULL,并且没有default,那么值是多少?

    由于 SQL Server 支持 ADD CONSTRAINT,我建议使用 Pavel 创建可空列的方法,然后在用非NULL 值填充后添加 NOT NULL 约束。

    【讨论】:

    • MySQL 支持将非空列添加到包含数据的现有表中,其中将数据类型的“合理”空值提供给现有行(即,0.0 表示浮点数,0 表示整数,空字符串表示字符串等)。
    【解决方案5】:

    这对我有用,也可以从设计视图中“借用”,进行更改 -> 右键单击​​ -> 生成更改脚本。

    BEGIN TRANSACTION
    GO
    ALTER TABLE dbo.YOURTABLE ADD
        YOURCOLUMN bit NOT NULL CONSTRAINT DF_YOURTABLE_YOURCOLUMN DEFAULT 0
    GO
    COMMIT
    

    【讨论】:

      【解决方案6】:
      ALTER TABLE `MY_TABLE` ADD COLUMN `STAGE` INTEGER UNSIGNED NOT NULL AFTER `PREV_COLUMN`;
      

      【讨论】:

        【解决方案7】:
        Alter TABLE 'TARGET' add 'ShouldAddColumn' Integer Not Null default "0"
        

        【讨论】:

        • 这个答案对这个话题有什么作用?
        【解决方案8】:

        更快的解决方案

        如果您像我一样需要在包含大量数据的表上执行此操作,则 ADD-UPDATE-ALTER 选项非常慢(可能需要数小时才能处理数百万行)。

        如果您也不想在表上使用默认值,这里是创建列和删除默认约束的完整代码(即使对于大型表也几乎是即时的):

        ALTER TABLE my_table ADD column_name INT NOT NULL CONSTRAINT my_table_default_constraint DEFAULT 0
        GO
        
        ALTER TABLE my_table DROP CONSTRAINT my_table_default_constraint 
        GO
        

        这是用于 SQL Server 的

        【讨论】:

          猜你喜欢
          • 2012-10-03
          • 2014-11-19
          • 1970-01-01
          • 1970-01-01
          • 2016-06-15
          • 2018-11-10
          • 2020-04-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多