我应该编写一个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'附近。
有人可以帮助我吗?
答案 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