Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server 2016游标代码正在使我的SSMS应用程序崩溃,需要提供建议_Sql Server_Tsql - Fatal编程技术网

Sql server SQL Server 2016游标代码正在使我的SSMS应用程序崩溃,需要提供建议

Sql server SQL Server 2016游标代码正在使我的SSMS应用程序崩溃,需要提供建议,sql-server,tsql,Sql Server,Tsql,我正在Windows 10上运行SSMS,当我在SP中找到此光标代码时,它正在使我的SSMS应用程序崩溃 我有一个临时表,我正试图用这个游标更新每个数字列,它看起来像这样: 我继承了下面的光标,它实际上正在破坏我桌面上的SSM: DECLARE db_cursor CURSOR FOR SELECT DISTINCT a.PolicyID, a.tenurestartyearmonth, a.TotalnMonthDurationDR FROM #Tenuretmp a INNER JOI

我正在Windows 10上运行SSMS,当我在SP中找到此光标代码时,它正在使我的SSMS应用程序崩溃

我有一个临时表,我正试图用这个游标更新每个数字列,它看起来像这样:

我继承了下面的光标,它实际上正在破坏我桌面上的SSM:

DECLARE db_cursor CURSOR FOR  
SELECT DISTINCT a.PolicyID, a.tenurestartyearmonth, a.TotalnMonthDurationDR 
FROM #Tenuretmp a
INNER JOIN (
    SELECT policyid, MAX(TotalnMonthDurationDR) tot
    FROM #Tenuretmp
    GROUP BY PolicyID
    --ORDER BY PolicyID asc
) b 
ON a.PolicyID = b.PolicyID 
AND a.TotalnMonthDurationDR = b.tot
ORDER BY a.TenureStartyearmonth asc, a.PolicyID asc;

OPEN db_cursor  
FETCH NEXT FROM db_cursor INTO @PolicyID, @tenurestartyearmonth, @TotalnMonthDurationDR

WHILE @@FETCH_STATUS = 0  
BEGIN  
    ----------------------------------------------------------------------------------------------

    SELECT @i = 0, @columns = N'' --,  @one = N'';

        WHILE @i < @TotalnMonthDurationDR
        BEGIN
            SET @columns =  @columns + ',' + ' [' + cast((@i+1) as nvarchar) +  ']  =  [' + cast((@i+1) as nvarchar) +  '] + 1' SET @i = @i + 1;
        END

        SET @sql = 'Update #Survivaltmp SET ' + STUFF(@columns, 1, 1, '') + ' WHERE Vintageyearmonth =' + @tenurestartyearmonth + ''

        exec (@sql)

    ----------------------------------------------------------------------------------------------------
    FETCH NEXT FROM db_cursor INTO @PolicyID, @tenurestartyearmonth, @TotalnMonthDurationDR
END  

CLOSE db_cursor  
DEALLOCATE db_cursor
我想在WHILE循环语句中进行更新,但无法确定如何使用结果集。我以前从未使用过游标,如有任何建议/帮助,将不胜感激


谢谢。

看起来光标正在为内部循环的每次迭代更新表。在没有数据的情况下,我只是根据您的代码在做什么来猜测它可能是什么样子。我将下面的内容拼凑在一起,作为一个可能的指针,以远离光标选项。它使用一个CTE将您的数据交叉应用于理货表,然后使用另一个CTE将这些结果转换为数字列,最后将它们分组为tenurestartyearmonth并对数字列求和。然后我们从第二个CTE中选择

我创建了一个具有完全相同结构的SurvivalTemp表,尽管Vintageyearmonth作为tenurestartyearmonth保留,并使用相同的伪数据集对其运行游标,并使用这两种方法返回相同的结果。您可以在此处进行测试:

更新版本:

这不使用CTE。相反,它使用另一个临时表来存储以前spanBuilder的结果。然后使用该表动态生成列信息。这个新的例子我添加了另一个记录,用了45个月来演示。我还将其更新为保留NULL,而不是0。它仍然是一个INT,但我认为数据类型转换可能是这里最简单的部分

DECLARE @cols AS NVARCHAR(MAX),
    @colsDefined AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SELECT DISTINCT a.PolicyID, a.tenurestartyearmonth, a.TotalnMonthDurationDR, 
c.*
INTO #spanBuilderTempTable
FROM #Tenuretmp a
INNER JOIN (
    SELECT policyid, MAX(TotalnMonthDurationDR) tot
    FROM #Tenuretmp
    GROUP BY PolicyID
    --ORDER BY PolicyID asc
) b 
ON a.PolicyID = b.PolicyID 
AND a.TotalnMonthDurationDR = b.tot
CROSS apply (
SELECT val = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
    FROM (VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) a(val)
    CROSS JOIN (VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) b(val)
    CROSS JOIN (VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) c(val)
    CROSS JOIN (VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) d(val)) AS c
WHERE c.val <= b.tot AND c.val >= 1


SELECT @cols = STUFF((SELECT ',' + QUOTENAME(c.val) 
        FROM #spanBuilderTempTable c
        GROUP BY c.val
        ORDER BY CAST(REPLACE(REPLACE(c.val,'[',''),']','') AS INT)
        FOR XML PATH('') , TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'') 

SELECT @colsDefined = STUFF((SELECT ',' + 'iif(sum(' + QUOTENAME(c.val) + ')=0,NULL,sum(' + QUOTENAME(c.val) + ')) as ' + QUOTENAME(c.val) +''
    FROM #spanBuilderTempTable c
    GROUP BY c.val
    ORDER BY CAST(REPLACE(REPLACE(c.val,'[',''),']','') AS INT)
    FOR XML PATH('') , TYPE
    ).value('.', 'NVARCHAR(MAX)') 
,1,1,'') 

set @query = 'SELECT tenurestartyearmonth, ' + @colsDefined + ' from 
            (
                select tenurestartyearmonth
                    , val
                from #spanBuilderTempTable
           ) SourceTable
            pivot 
            (
                 count(val)
                for val in (' + @cols + ')
            ) PivotTable 
            GROUP BY PivotTable.tenurestartyearmonth'


EXEC(@query)

检查事件日志以查看SSMS崩溃时的错误。是否所有其他游标都不会使SSMS崩溃?是否尝试使用CLI界面sqlcmd执行它直到结束?有时,当结果选项卡中有许多行和列时,SSMS会异常崩溃,因为图形界面使用32位子系统,无法分配超过2GB的内存。最后,您还可以尝试按此处所述的文本格式设置结果,以避免繁重的图形渲染。谢谢你的回复。在我的Windows 10框中的事件日志中,我似乎找不到SSMS崩溃3。我们并没有在PROD中运行的游标。写这篇文章的人已经不在这里了。若你们不介意的话,请提问,正如您所看到的,@列是动态构建的,我不知道在给定的时间段内会有多少列,我想知道如何在您单独定义的SELECT in spanFinder中解释这些列?对不起,我从来没有交叉申请过。希望这是有道理的。谢谢你的帮助和时间。Survival是动态构建的吗?如果您对可能的最长月持续时间有任何想法,您可以在此基础上预定义它。当前,如果某个期间只有(比如)2个月的条目,则该期间的其他列将显示为0。如果我们完全不确定可以拥有多少潜在的max列,那么我们需要动态构建模式和透视。这不会很有趣:是的,Survivaltmp是动态构建的。我有每个月的最大月持续时间值。此外,客户不希望在其他列中使用0,但希望使用空字符串,这是Survivaltmp表在填充之前所具有的字符串。我已将其更新为动态生成列。是的。抱歉,我在代码中遗漏了一些内容。明白了。谢谢你所有的时间和帮助。我很感激,也学到了很多。
DECLARE @cols AS NVARCHAR(MAX),
    @colsDefined AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SELECT DISTINCT a.PolicyID, a.tenurestartyearmonth, a.TotalnMonthDurationDR, 
c.*
INTO #spanBuilderTempTable
FROM #Tenuretmp a
INNER JOIN (
    SELECT policyid, MAX(TotalnMonthDurationDR) tot
    FROM #Tenuretmp
    GROUP BY PolicyID
    --ORDER BY PolicyID asc
) b 
ON a.PolicyID = b.PolicyID 
AND a.TotalnMonthDurationDR = b.tot
CROSS apply (
SELECT val = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
    FROM (VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) a(val)
    CROSS JOIN (VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) b(val)
    CROSS JOIN (VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) c(val)
    CROSS JOIN (VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) d(val)) AS c
WHERE c.val <= b.tot AND c.val >= 1


SELECT @cols = STUFF((SELECT ',' + QUOTENAME(c.val) 
        FROM #spanBuilderTempTable c
        GROUP BY c.val
        ORDER BY CAST(REPLACE(REPLACE(c.val,'[',''),']','') AS INT)
        FOR XML PATH('') , TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'') 

SELECT @colsDefined = STUFF((SELECT ',' + 'iif(sum(' + QUOTENAME(c.val) + ')=0,NULL,sum(' + QUOTENAME(c.val) + ')) as ' + QUOTENAME(c.val) +''
    FROM #spanBuilderTempTable c
    GROUP BY c.val
    ORDER BY CAST(REPLACE(REPLACE(c.val,'[',''),']','') AS INT)
    FOR XML PATH('') , TYPE
    ).value('.', 'NVARCHAR(MAX)') 
,1,1,'') 

set @query = 'SELECT tenurestartyearmonth, ' + @colsDefined + ' from 
            (
                select tenurestartyearmonth
                    , val
                from #spanBuilderTempTable
           ) SourceTable
            pivot 
            (
                 count(val)
                for val in (' + @cols + ')
            ) PivotTable 
            GROUP BY PivotTable.tenurestartyearmonth'


EXEC(@query)