在现有表中插入 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 列的主要内容,如果未能解决你的问题,请参考以下文章
如何在 App Script 中加入两个表并将数据提取到大查询现有表中