@ypercubeの答えは、メタデータのみの変更としてこれを部分的に管理します。
制約を追加NOCHECK
すると、検証のために行を読み取る必要がなくなり、列にNULL
値が含まれていない位置から開始する場合(および制約のチェックと追加の間に何も追加されないことがわかっている場合)、制約によりNULL
、将来INSERT
またはUPDATE
操作から値が作成されないため、これは機能します。
ただし、制約を追加すると、並行トランザクションに影響を与える可能性があります。ALTER TABLE
取得する必要があります。Sch-M
最初のロックを。これを待っている間、他のすべてのテーブルアクセスは、ここで説明するようにブロックされます。
Sch-M
ただし、ロックが取得されると、操作は非常に高速になります。
これに関する問題の1つは、実際に列に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)
これをより単純なものと比較してください
ALTER TABLE T ALTER COLUMN X INT NOT NULL
SELECT *
FROM T
WHERE X NOT IN (SELECT X FROM T)
この方法で列定義を変更する際に発生する可能性のある問題の1つは、すべての行を読み取って条件を満たしていることを確認する必要があるだけでなく、実際に行の更新をログに記録できることです。
考えられる半分の方法は、チェック制約を追加することWITH CHECK
です。これは、WITH NOCHECK
すべての行を読み取る必要があるため遅くなりますが、クエリオプティマイザーが上記のクエリでより単純なプランを提供できるようにし、ログに記録される更新の問題を回避する必要があります。