在现有表中插入 NOT NULL 列

Posted

技术标签:

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

我试过了:

ALTER TABLE MY_TABLE 
ADD STAGE INT NOT NULL;

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

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

【问题讨论】:

【参考方案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 的

【讨论】:

以上是关于在现有表中插入 NOT NULL 列的主要内容,如果未能解决你的问题,请参考以下文章

重组现有 SQL Server 表中的序列

如何在 App Script 中加入两个表并将数据提取到大查询现有表中

更新查询以根据不同表中的值更改一个表中列的现有值

使用现有数据库表中的用户名和密码在 Blazor 中进行身份验证?

如何知道已使用哪种算法加密表中的现有密码

如何使用 terraform 在 OCI 中的现有默认路由表中添加新规则