在动态T-SQL中更新标识列

时间:2014-12-11 21:25:07

标签: sql sql-server tsql cursor dynamic-sql

我应该编写一个SQL脚本,我在其中使用动态游标。我想要reidentity表行并编写存储过程:

CREATE PROCEDURE [dbo].[ReidentityComments]
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE Reidentitier CURSOR
        LOCAL
        SCROLL
        DYNAMIC
        FOR
            SELECT * FROM Comment
        FOR UPDATE;

    OPEN Reidentitier;

    DECLARE @CommentId INT;
    DECLARE @FilmId INT;
    DECLARE @Text NVARCHAR(2000);
    DECLARE @PlacingDate DATETIME;
    DECLARE @UserId INT;

    DECLARE @current INT;
    SET @current = 1;

    DECLARE @updateSql NVARCHAR(100);
    SET @updateSql = N'
        SET IDENTITY_INSERT VideoLibrary.dbo.Comment ON;
        UPDATE Comment SET CommentId = @cur WHERE CommentId = @id;
        SET IDENTITY_INSERT VideoLibrary.dbo.Comment OFF;
    ';

    DECLARE @params NVARCHAR(100);
    SET @params = N'@cur INT, @id INT';

    FETCH NEXT
        FROM Reidentitier
        INTO @CommentId, @FilmId, @Text, @PlacingDate, @UserId;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF @CommentId != @current
            EXECUTE sp_executesql @updateSql, @params, @cur = @current, @id = @CommentId;

        FETCH NEXT
            FROM Reidentitier
            INTO @CommentId, @FilmId, @Text, @PlacingDate, @UserId;

        SET @current = @current + 1;
    END
END

但是当我尝试执行该过程时,我收到错误:

  

在预期条件的上下文中指定的非布尔类型的表达式,在'Co'附近。

有人可以帮助我吗?

2 个答案:

答案 0 :(得分:2)

代码中的问题出在@updateSql的声明中 nvarchar(100)太小而无法存储整个字符串。它被截断了,你最终会得到类似......

的结果
SET IDENTITY_INSERT VideoLibrary.dbo.Comment ON;
UPDATE Comment SET CommentId = @cur WHERE CommentId

当错误被返回时...

那就是说,i.m.h.o。做你想做的事情的更好方法可能是:

SELECT IDENTITY (int, 1, 1) AS CommentId, FilmId, Text, PlacingDate, UserId
INTO TMP_COMMENT
FROM Comment;

exec SP_RENAME Comment, OLD_COMMENT;
exec SP_RENAME TMP_COMMENT, Comment;

此方法的唯一缺点是不会在新注释表上创建任何索引或主键。

答案 1 :(得分:0)

无论如何,您都无法更新标识列(无论Identity_insert值如何)。

所以要解决你的问题 - 它真的需要成为标识列吗? (如果您的数据引用了注释表,那么如果Identity列也是主键,则可能会遇到问题。)

你能创建一个名为RowNum的列(例如) - 并使用Row_Number()重新填充 吗?

例如

UPDATE Comment SET RowNum = c.NewSequence
FROM (
      SELECT CommentId, NewSequence = ROW_NUMBER() OVER (ORDER BY CommentId)
      FROM Comments) c
WHERE c.Id = Comment.id