当索引依赖于该列而不重新创建索引时,如何将列从 null 更改为非 null?
Posted
技术标签:
【中文标题】当索引依赖于该列而不重新创建索引时,如何将列从 null 更改为非 null?【英文标题】:How do I change a column from null to not null when an index depends on that column without recreating the index? 【发布时间】:2014-10-19 16:04:40 【问题描述】:我有一列 Column
被声明为 NULL DEFAULT(GETUTCDATE())
并且有一个包含此列的非聚集索引。我想将此列更改为NOT NULL DEFAULT(GETUTCDATE())
,当我运行ALTER TABLE ALTER COLUMN
语句时,SQL Azure 服务说它无法更改该列,因为有一个取决于该列的索引。
这是一个生产数据库,该表包含大约一千万条记录。所以我宁愿不删除并重新创建索引,因为这会减慢数据库的速度(尤其是创建索引可能需要几分钟)。
如何在不重新创建索引的情况下更改列?
【问题讨论】:
相关:***.com/questions/1258380/… 我已经在本地服务器(即不是 Azure)上的 SQL Server 2012 SP1 上对此进行了测试,但它也不起作用。因此很可能有必要删除索引并在 Azure 上重新创建它。 ALTER TABLE Children ALTER COLUMN ChildName VARCHAR(50) NOT NULL 产生:Msg 5074,Level 16,State 1,Line 1 索引“IX_Children_ChildName”取决于列“ChildName”。消息 4922,级别 16,状态 9,第 1 行 ALTER TABLE ALTER COLUMN ChildName 失败,因为一个或多个对象访问此列。 (当然,无论如何都要检查列中是否没有NULL,这将是一个错误ev 【参考方案1】:不必更改表列以强制执行 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
【讨论】:
赞成,因为它提供了一个具有问题设置的约束的解决方案,但对于长期可支持性而言,理想情况下,该列似乎会在某个时间点发生变化,而它所花费的时间不会影响用户。以上是关于当索引依赖于该列而不重新创建索引时,如何将列从 null 更改为非 null?的主要内容,如果未能解决你的问题,请参考以下文章