又一个“光标是只读的。”?

问题描述 投票:0回答:2

我的问题与其他同类问题不同,因为我确实需要一个游标来重建多个索引。然而,我想利用我已经在光标处的事实并进行更新。

这是 SQL 代码:

USE [MyDB]
DECLARE @TableName NVARCHAR(128)
DECLARE @IndexName NVARCHAR(128)
DECLARE @Sql NVARCHAR(MAX)

BEGIN TRY 
    DECLARE c CURSOR LOCAL FORWARD_ONLY KEYSET SCROLL_LOCKS FOR
    SELECT TableName,IndexName
    FROM _NonClusteredIndices_ i
    JOIN _Candidates_ c ON i.ObjectId = c.ObjectId
    WHERE State = 1
    ORDER BY TableName,IndexName
    FOR UPDATE OF i.State
    OPEN c
    FETCH NEXT FROM c INTO @TableName,@IndexName
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @Sql = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REBUILD'
        EXEC(@Sql)
        UPDATE _NonClusteredIndices_ SET State = 2 WHERE CURRENT OF c
        FETCH NEXT FROM c INTO @TableName,@IndexName
    END
    CLOSE c
    DEALLOCATE c
END TRY
BEGIN CATCH
    SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() as ErrorState,
        ERROR_PROCEDURE() as ErrorProcedure,
        ERROR_LINE() as ErrorLine,
        ERROR_MESSAGE() as ErrorMessage;
END CATCH

唉,我明白了光标是只读的

为什么?我该如何解决它?

编辑

两个表的DDL为:

USE [MyDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[_Candidates_](
    [ObjectId] [int] NOT NULL,
    [ClientIdColumnId] [int] NOT NULL,
    [TableName] [nvarchar](128) NOT NULL,
    [ClientIdColumnName] [nvarchar](128) NOT NULL,
    [RowCount] [bigint] NOT NULL
) ON [PRIMARY]

CREATE TABLE [dbo].[_NonClusteredIndices_](
    [ObjectId] [int] NOT NULL,
    [IndexName] [nvarchar](128) NOT NULL,
    [State] [int] NOT NULL DEFAULT ((0))
) ON [PRIMARY]

(哎呀,列出了错误的表格)

除了

_NonClusteredIndices_.State
列的默认约束之外,所有表都没有任何索引或约束。

sql-server t-sql sql-server-2012
2个回答
1
投票
如果

CURSOR

 引用的表之一没有唯一索引,则 
CURSOR
 将转换为 
STATIC
STATIC
 光标为 
READ-ONLY
。请参阅
使用隐式游标转换了解更多信息。

作为替代方案,我建议您完全摆脱

CURSOR

 并使用基于集合的查询来执行此操作:

DECLARE @sql NVARCHAR(MAX) = ''; BEGIN TRY BEGIN TRANSACTION SELECT @sql = @sql + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(TableName) + ' REBUILD;' + CHAR(10) FROM _NonClusteredIndices_ i JOIN _Candidates_ c ON i.ObjectId = c.ObjectId WHERE State = 1; EXEC(@sql); UPDATE i SET i.State = 2 FROM _NonClusteredIndices_ i JOIN _Candidates_ c ON i.ObjectId = c.ObjectId WHERE State = 1; COMMIT TRANSACTION END TRY BEGIN CATCH IF @@TRANCOUNT > 0 BEGIN ROLLBACK TRANSACTION END DECLARE @ErrorNumber INT, @ErrorMessage NVARCHAR(4000), @ErrorState INT, @ErrorSeverity INT, @ErrorLine INT; SELECT @ErrorNumber = ERROR_NUMBER(), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(), @ErrorLine = ERROR_LINE(), @ErrorMessage = ERROR_MESSAGE(); RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState); END CATCH
    

0
投票
我没有在任何地方看到以下评论..甚至没有在微软网站上讨论

隐式光标转换

当游标的 SELECT 语句包含 LEAD 或 LAG 函数时,游标将变为 READ ONLY。

© www.soinside.com 2019 - 2024. All rights reserved.