我只是设计了一个新系统的原型,将我们其中一个数据库中的某些操作推迟到几个小时之后。我想出了一个非常简单的模式。我是SQLServer2005Express上的第一个原型,但在2008开发人员上确认了同样的问题。我得到的错误是:
消息8646,级别21,状态1,程序
取消,第6行找不到索引
表的索引ID 1中的条目
277576027,在数据库“XXXXXX”中。这个
指示的索引已损坏或存在
当前更新有问题
计划。运行DBCC CHECKDB或DBCC
检查表。如果问题仍然存在,
联系产品支持。
我使用的模式是:
create schema Writeback authorization dbo
create table Deferrals (
ClientID uniqueidentifier not null,
RequestedAt datetime not null,
CompletedAt datetime null,
CancelledAt datetime null,
ResolvedAt as ISNULL(CompletedAt,CancelledAt) persisted,
constraint PK_Writeback_Deferrals PRIMARY KEY (ClientID,RequestedAt) on [PRIMARY],
constraint CK_Writeback_Deferrals_NoTimeTravel CHECK ((RequestedAt <= CompletedAt) AND (RequestedAt <= CancelledAt)),
constraint CK_Writeback_Deferrals_NoSchrodinger CHECK ((CompletedAt is null) or (CancelledAt is null))
/* TODO:FOREIGN KEY */
)
create view Pending with schemabinding as
select
ClientID
from
Writeback.Deferrals
where
ResolvedAt is null
go
alter table Writeback.Deferrals add constraint
DF_Writeback_Deferrals_RequestedAt DEFAULT CURRENT_TIMESTAMP for RequestedAt
go
create unique clustered index PK_Writeback_Pending on Writeback.Pending (ClientID)
go
create procedure Writeback.Defer
@ClientID uniqueidentifier
as
set nocount on
insert into Writeback.Deferrals (ClientID)
select @ClientID
where not exists(select * from Writeback.Pending where ClientID = @ClientID)
go
create procedure Writeback.Cancel
@ClientID uniqueidentifier
as
set nocount on
update
Writeback.Deferrals
set
CancelledAt = CURRENT_TIMESTAMP
where
ClientID = @ClientID and
CompletedAt is null and
CancelledAt is null
go
create procedure Writeback.Complete
@ClientID uniqueidentifier
as
set nocount on
update
Writeback.Deferrals
set
CompletedAt = CURRENT_TIMESTAMP
where
ClientID = @ClientID and
CompletedAt is null and
CancelledAt is null
go
引发错误的代码如下:
declare @ClientA uniqueidentifier
declare @ClientB uniqueidentifier
select @ClientA = newid(),@ClientB = newid()
select * from Writeback.Pending
exec Writeback.Defer @ClientA
select * from Writeback.Pending
exec Writeback.Defer @ClientB
select * from Writeback.Pending
exec Writeback.Cancel @ClientB --<-- Error being raised here
select * from Writeback.Pending
exec Writeback.Complete @ClientA
select * from Writeback.Pending
select * from Writeback.Deferrals
我见过其他一些人遇到这样的问题,但他们的视图中似乎有聚合(从MS发回的一条消息说,他们将在2005年的SP1中删除创建此类索引视图的能力),或者他们通过在join子句中应用merge join来解决这个问题(但我没有)。
最初,deferrals表中没有计算列,视图中的where子句分别测试completedat和cancelledat列是否为空。但我改为上面的内容,只是想看看我是否能挑起不同的行为。
我所有的设置选项都适合使用索引视图,如果没有,我希望抛出一个不那么猛烈的错误。
有什么想法吗?