【问题标题】:How do I change a column from null to not null when an index depends on that column without recreating the index?当索引依赖于该列而不重新创建索引时,如何将列从 null 更改为非 null?
【发布时间】:2014-10-19 16:04:40
【问题描述】:

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

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

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

【问题讨论】:

  • 我已经在本地服务器(即不是 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

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


【解决方案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

【讨论】:

  • 赞成,因为它提供了一个具有问题设置的约束的解决方案,但对于长期可支持性而言,理想情况下,该列似乎会在某个时间点发生变化,而它所花费的时间不会影响用户。
猜你喜欢
  • 2012-01-29
  • 2015-05-25
  • 2010-09-16
  • 2014-08-19
  • 2018-04-03
  • 1970-01-01
  • 1970-01-01
  • 2017-05-22
  • 2016-01-10
相关资源
最近更新 更多