如果索引依赖于该列而不重新创建索引,如何将列从null更改为非null?

时间:2014-08-26 10:49:25

标签: sql-server database azure-sql-database database-indexes alter-column

我有一个列Column,它被声明为NULL DEFAULT(GETUTCDATE()),并且包含此列的非聚集索引。我想将此列更改为NOT NULL DEFAULT(GETUTCDATE()),当我运行ALTER TABLE ALTER COLUMN语句时,SQL Azure服务表示它无法更改列,因为索引取决于此列。

这是一个生产数据库,该表包含大约一千万条记录。所以我不想删除并重新创建索引,因为这会降低数据库的速度(特别是创建索引可能需要几分钟)。

如何在不重新创建索引的情况下更改列?

1 个答案:

答案 0 :(得分:3)

不必更改表列以强制执行NOT NULL。而是可以向表中添加新约束:

ALTER TABLE [Table] WITH CHECK
   ADD CONSTRAINT [TableColumnNotNull] CHECK ([Column] Is NOT NULL);

这不会影响索引,但优化器会使用此约束来提高性能:

CREATE TABLE Test (ID bigint PRIMARY KEY, [Column] DATE NULL DEFAULT(GETUTCDATE()));
GO --< Create test table

CREATE NONCLUSTERED INDEX TestColumnIdx ON Test ([Column]);
GO --< Create the index

ALTER TABLE Test ALTER COLUMN [Column] DATE NOT NULL;
GO --< That won't work: the index 'TestColumnIdx' is dependent on column 'Column'

Select * From Test Where [Column] Is NULL;
GO --< Check the plan: it has "Index Seek (NonClustered)"

ALTER TABLE Test WITH CHECK ADD CONSTRAINT TestColumnNotNull CHECK ([Column] Is NOT NULL);
GO --< Add a "stand-alone" NOT NULL constraint

Select * From Test Where [Column] Is NULL;
GO --< Check the plan: it has "Constant Scan" now

DROP TABLE Test;
GO --< Clean-up