要将 NOT NULL 列添加到包含许多记录的表中,需要应用 DEFAULT 约束。如果表非常大,此约束会导致整个 ALTER TABLE 命令需要很长时间才能运行。这是因为:
假设:
- DEFAULT 约束修改现有记录。这意味着数据库需要增加每个记录的大小,这会导致它将完整数据页上的记录转移到其他数据页,并且这需要时间。
- DEFAULT 更新作为原子事务执行。这意味着事务日志需要增长,以便在必要时可以执行回滚。
- 事务日志跟踪整个记录。因此,即使只修改单个字段,日志所需的空间也将基于整个记录的大小乘以现有记录的数量。这意味着,即使两个表的记录总数相同,向包含小记录的表添加列也会比向包含大记录的表添加列更快。
可能的解决方案:
- 吸起它并等待该过程完成。只要确保将超时时间设置得很长即可。这样做的问题是,根据记录的数量,可能需要几个小时或几天的时间才能完成。
- 添加列但允许 NULL。然后,运行 UPDATE 查询来设置现有行的 DEFAULT 值。不要执行更新*。一次更新一批记录,否则您最终会遇到与解决方案 #1 相同的问题。这种方法的问题在于,当您知道这是一个不必要的选项时,您最终会得到一个允许 NULL 的列。我相信有一些最佳实践文档指出,除非有必要,否则不应拥有允许 NULL 的列。
- 创建具有相同架构的新表。将列添加到该架构中。将原始表中的数据转移过来。删除原始表并重命名新表。我不确定这比#1 更好。
问题:
- 我的假设正确吗?
- 这些是我唯一的解决方案吗?如果是的话,哪一个最好?如果没有,我还能做什么?
我的工作也遇到了这个问题。我的解决方案是#2。
这是我的步骤(我使用的是 SQL Server 2005):
1)将列添加到表中并使用默认值:
ALTER TABLE MyTable ADD MyColumn varchar(40) DEFAULT('')
2)添加一个NOT NULL
约束与NOCHECK
选项。这NOCHECK
不强制执行现有值:
ALTER TABLE MyTable WITH NOCHECK
ADD CONSTRAINT MyColumn_NOTNULL CHECK (MyColumn IS NOT NULL)
3)增量更新表中的值:
GO
UPDATE TOP(3000) MyTable SET MyColumn = '' WHERE MyColumn IS NULL
GO 1000
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)