我有一个现有的表约有4亿行.该表包含一组名为IsModified,IsDeleted和IsExpired的位列.
CREATE TABLE [dbo].[ActivityAccumulator]( [ActivityAccumulator_SK] [int] IDENTITY(1,1) NOT NULL,[ActivityAccumulatorPK1] [int] NULL,[UserPK1] [int] NULL,[Data] [varchar](510) NULL,[CoursePK1] [int] NULL,[TimeStamp] [datetime] NULL,[SessionID] [int] NULL,[Status] [varchar](50) NULL,[EventType] [varchar](40) NULL,[DWCreated] [datetime] NULL,[DWModified] [datetime] NULL,[IsModified] [bit] NULL,[DWDeleted] [datetime] NULL,[IsDeleted] [bit] NULL,[ActivityAccumulatorKey] [bigint] NULL,[ContentPK1] [bigint] NULL ) ON [PRIMARY]
我想为表添加一个默认约束,对于所有未来插入的行,将这些位列默认为0.我试图通过以下命令执行此操作:
ALTER TABLE ActivityAccumulator ADD CONSTRAINT DF_ActivityAccumulatorIsExpired DEFAULT (0) FOR IsExpired ALTER TABLE ActivityAccumulator ADD CONSTRAINT DF_ActivityAccumulatorIsDeleted DEFAULT (0) FOR IsDeleted ALTER TABLE ActivityAccumulator ADD CONSTRAINT DF_ActivityAccumulatorIsModified DEFAULT (0) FOR IsModified
我最终想回去清理现有的数据,将零值放在有NULL值的地方,但现在我并不需要这样做.
只是尝试运行第一个ADD CONSTRAINT命令已经执行了一个多小时.鉴于我不想改变任何现有的价值观,为什么这么长时间?
解决方法
一种可能性是您的服务器上有另一个进程锁定此表.
想像一下,我打开了两个SSMS窗口,第一个执行这些命令:
-- Session 1 CREATE TABLE Foo(IsTrue BIT) INSERT INTO Foo VALUES (1),(1),(0) BEGIN TRANSACTION UPDATE Foo SET IsTrue = 1 - IsTrue
然后将SSMS窗口打开,使事务永远不会关闭,尝试在其他SSMS会话中执行此简单约束命令将永久挂起:
-- Session 2 ALTER TABLE Foo ADD CONSTRAINT FooDefault DEFAULT(0) FOR IsTrue
请注意,在此示例中,表的大小或复杂性是无关紧要的;我被迫等待交易完成.在我通过提交交易或关闭会话1释放Foo上的锁之后,会话2中的alter指令将不会完成.
你怎么知道这是你的问题?看看SSMS活动监视器中的“进程”列表.如果您的ALTER指令正在等待其他任务完成,“阻止”列中将显示一个数字,表示导致您的问题的命令的会话ID.
那个会议可能会等待另一个等等.如果您遵循这些引用,您最终会在“Head Blocker”列中找到一个具有1的进程.从那里你可以决定是否采取适当的行动来杀死违规进程,或者只是等待.