Jos*_*gle 12 sql-server-2008 null alter-table
我有一个包含数百万行和一个允许 NULL 值的列的表。但是,当前没有一行具有该列的 NULL 值(我可以通过查询快速验证这一点)。但是当我执行命令时
ALTER TABLE MyTable ALTER COLUMN MyColumn BIGINT NOT NULL;
Run Code Online (Sandbox Code Playgroud)
相对而言,查询需要永远。它实际上需要 10 到 20 分钟,是添加检查约束的两倍多。有没有办法立即更新该列的表元数据,尤其是因为我知道该列没有任何行具有 NULL 值?
Mar*_*ith 12
@ypercube 的答案确实部分地管理了这一点,因为元数据只发生了变化。
添加约束NOCHECK
意味着不需要读取任何行来验证它,并且如果您从列不包含NULL
值的位置开始(如果您知道在检查和添加约束之间不会添加任何值),那么,由于约束阻止NULL
从未来INSERT
或UPDATE
操作中创建值,这将起作用。
但是,添加约束仍然会对并发事务产生影响。在ALTER TABLE
将需要获得一个Sch-M
第一锁。当它等待此操作时,所有其他表访问都将被阻止,如此处所述。
Sch-M
然而,一旦获得锁,操作应该很快。
这样做的一个问题是,即使您知道该列实际上没有NULL
s,查询优化器也不信任该约束,这意味着计划可能是次优的。
CREATE TABLE T (X INT NULL)
INSERT INTO T
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values
ALTER TABLE T WITH NOCHECK
ADD CONSTRAINT X_NOT_NULL
CHECK (X IS NOT NULL) ;
SELECT *
FROM T
WHERE X NOT IN (SELECT X FROM T)
Run Code Online (Sandbox Code Playgroud)
将此与更简单的进行比较
ALTER TABLE T ALTER COLUMN X INT NOT NULL
SELECT *
FROM T
WHERE X NOT IN (SELECT X FROM T)
Run Code Online (Sandbox Code Playgroud)
以这种方式更改列定义时可能会遇到的一个问题是,它不仅需要读取所有行以验证它们是否满足条件,而且还可能最终实际对行执行记录更新。
一个可能的中途之家可能是添加检查约束WITH CHECK
。这将比WITH NOCHECK
它需要读取所有行慢,但它确实允许查询优化器在上面的查询中给出更简单的计划,并且应该避免可能的记录更新问题。
您可以CHECK
使用以下NOCHECK
选项添加表约束,而不是更改列:
ALTER TABLE MyTable WITH NOCHECK
ADD CONSTRAINT MyColumn_NOT_NULL
CHECK (MyColumn IS NOT NULL) ;
Run Code Online (Sandbox Code Playgroud)