我有一段脚本使用游标来排序表中的行。例如,表格如下所示, SSN,Kid_SSN,Kid_DOB,Seq#列出每个有1个或更多孩子的人。我想更新Seq#,根据出生日期将每个孩子标记为1,2,3 ... 我使用游标进行更新,以便在SQL Server 2008中成功完成。我目前的麻烦是,这个相同的脚本无法在sql server 2012中按预期运行。问题出在SQL 2012游标提取NEXT超过1行一次。所以问题是我在哪里可以设置光标提取大小?我四处搜索,但没有得到很好的答案。 这里有人可以解决一些问题吗?感谢。
Scrip看起来像这样:
DECLARE @SocialSecurity varchar(9), @PersonID int, @Dep_SSN varchar(9)
DECLARE @LastName varchar(20), @FirstName varchar(20), @BirthDate datetime,
@Number int
DECLARE @ssn varchar(9) = '000000000'
DECLARE @Mem int = 1
DECLARE cur cursor
FOR SELECT * FROM kids
FOR UPDATE OF Number;
OPEN cur;
FETCH NEXT FROM cur INTO @SocialSecurity, @PersonID, @Dep_SSN, @LastName, @FirstName,
@BirthDate, @Number;
WHILE @@FETCH_STATUS = 0
BEGIN
IF @SocialSecurity = @ssn
BEGIN
UPDATE kids
SET Number = @Mem+1
WHERE CURRENT OF cur
SET @Mem = @Mem+1
END;
ELSE
BEGIN
SET @ssn = @SocialSecurity
SET @Mem = 1
END;
FETCH NEXT FROM cur INTO @SocialSecurity, @PersonID, @Dep_SSN, @LastName, @FirstName,
@BirthDate, @Number;
END;
CLOSE cur;
DEALLOCATE cur;
有关此问题的详细信息。 kids是由'SELECT .. INTO'生成的临时表,简化的集合看起来像这样
SSN Kid_SSN DOB Seq#
123123123 987987987 1/1/2000 1
123123123 987987988 1/1/2003 1
123123125 890890890 2/3/2002 1
因此所有seq#都被启动为1.在完成上面的脚本后,我希望桌面的孩子能够 看起来像这样
SSN Kid_SSN DOB Seq#
123123123 987987987 1/1/2000 1
123123123 987987988 1/1/2003 2
123123125 890890890 2/3/2002 1
该脚本在服务器2008 R2上完美地实现了这一点,但在服务器2012上却没有。此外,我发现它只更新了第88,176行等,如果适用的话。这就是为什么我认为游标一次获取88行。但是在服务器2008上,它显然按照我的预期一次获取1行。希望这能解释我的问题。 我想强制光标一次获取1行,使其在服务器2012上工作,尽管效率不高。或者,如何在不使用游标的情况下进行排序?感谢。
答案 0 :(得分:1)
用功能排名替换整个脚本会不会有效?
像
这样的东西select *, rank() over (partition by SSN, Kid_DOB order by Kid_SSN) as SeqNum
from kids
我认为这应该可行,如果没有,你可以通过调整分区和顺序来使它工作。
答案 1 :(得分:1)
您的脚本要求kids
上的光标按同一SSN对记录进行分组。但是没有ORDER BY来强制执行此操作。因此,记录以一些随机的顺序返回,这会混淆@Mem
计数器。
这不是SQL 2012与2008的问题。我相信你只是运气好了SQL 2008并且记录已经按照你想要的方式排序,或者SQL 2008有不同的行为来选择无序结果,或者你定义了pk和索引不同。