SQL Server中索引视图的问题,错误8646

时间:2009-07-03 09:31:27

标签: sql-server sql-server-2005 sql-server-2008

我正在为一个新系统做原型设计,推迟某些操作,直到我们的某个数据库出现非工作时间。我想出了一个非常简单的架构(我认为)。我是第一次在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选项看起来都适合使用索引视图,如果不是,我希望抛出一个不那么暴力的错误。

有什么想法吗?

2 个答案:

答案 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。