我正在为一个新系统做原型设计,推迟某些操作,直到我们的某个数据库出现非工作时间。我想出了一个非常简单的架构(我认为)。我是第一次在SQL Server 2005 Express上进行原型设计,但在2008 Developer上确认了同样的问题。我得到的错误是:
Msg 8646,Level 21,State 1,Procedure 取消,第6行无法找到索引 表的索引ID 1中的条目 277576027,在数据库'xxxxxx'中。该 指示索引已损坏或存在 当前更新的问题 计划。运行DBCC CHECKDB或DBCC CHECKTABLE。如果问题仍然存在, 联系产品支持。
我正在使用的架构是:
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 SP 1中创建此类索引视图的能力),或者他们通过在join子句中应用合并连接来解决它(但我没有)。
最初,Deferrals表中没有计算列,视图中的where子句分别测试了CompletedAt和CancelledAt列的NULL。但我改变了上述内容只是为了看看我是否能引发不同的行为。
我的所有SET选项看起来都适合使用索引视图,如果不是,我希望抛出一个不那么暴力的错误。
有什么想法吗?
答案 0 :(得分:0)
你有索引损坏。运行checkdb并查看它给你的错误。您可以做的最简单的事情就是重建索引。
如果它适用于您的情况,也请查看此KB article。
另请注意,将主键放在GUID列上会在其上创建聚簇索引,这是您可以做的最糟糕的表现。
答案 1 :(得分:0)
我设法找出导致此错误的原因,尝试从头开始构建此脚本,并在我去的时候添加碎片。
如果视图是作为CREATE SCHEMA语句的一部分创建的,则会产生某种错误。如果我将CREATE SCHEMA分成它自己的批处理,然后分批创建表和视图,一切正常。
漫长的过期编辑 - 我在Connect here上提出了这个问题。它被确认为SQL Server 2008中的一个问题。
内部版本(2010年)表明它不再是一个问题,我(刚才,2016)确认问题中的脚本在SQL Server 2012中没有生成相同的错误。修复程序没有回来 - 移植到SQL Server 2008。