删除SQL

时间:2018-03-11 19:05:05

标签: sql sql-server tsql cursor

总是不鼓励使用游标,它已广泛用于我们当前的存储过程并用基于集合的查询替换它们。但是这个特殊情况是一个,我没有得到使用基于集合的查询的解决方案,并被迫继续使用游标。我在下面提供代表方案的示例代码:

DECLARE @temp varchar(10), @continuechar varchar(10)
DECLARE  @table1 table (col1 varchar(10)) 

insert into @table1
select 'A' UNION
select 'B' UNION
select 'C' UNION
select 'D' UNION
select 'E' UNION
select 'F' UNION
select 'G' 

DECLARE Cursor1 CURSOR for select Col1 from @table1
open Cursor1

FETCH NEXT from Cursor1 into @temp
WHILE @@FETCH_STATUS = 0  
BEGIN
 if @temp='A'
 BEGIN
    set @continuechar=@temp  
 END
 if @temp='C'
 BEGIN
    set @continuechar=@temp
 END
select @continuechar, @temp
FETCH NEXT from Cursor1 into @temp
END
CLOSE cursor1;
deallocate cursor1

以上示例代码@continuechar变量未设置,每次光标执行时。如果设置了@continuechar,则后面的select语句提供的结果集的当前值为@continuechar:

select @continuechar, @temp

如果未设置,则使用先前设置的值来提供结果集。 我们可以设置基于查询来从这种情况中删除光标。

1 个答案:

答案 0 :(得分:0)

首先,我会添加一些id列以获得稳定排序。然后只需使用窗口函数:

  • SUM() OVER()计算群组
  • FIRST_VALUE() OVER()在组中传播第一个值 (从SQL Server 2012开始,如果需要,您可以与MAX(continuechar) OVER(PARTITION BY grp)交换)
DECLARE  @table1 table (id INT IDENTITY(1,1), col1 varchar(10)) 

insert into @table1
    select 'A' UNION
    select 'B' UNION
    select 'C' UNION
    select 'D' UNION
    select 'E' UNION
    select 'F' UNION
    select 'G';

WITH cte AS (
   SELECT id
        ,col1
        ,CASE WHEN col1 IN('A', 'C') THEN col1 END AS continuechar
        ,SUM(CASE WHEN col1 IN ('A', 'C') THEN 1 ELSE 0 END)
                  OVER(ORDER BY id) AS grp
   FROM @table1
)
SELECT id, col1,
   FIRST_VALUE(continuechar) OVER(PARTITION BY grp ORDER BY id) AS continuechar
FROM cte
ORDER BY id;

<强> DBFiddle Demo

修改

Quirky update这仅适用于纯粹演示。不要在生产系统上使用此方法:

DECLARE  @table1 table (id INT IDENTITY(1,1) PRIMARY KEY, col1 varchar(10),
                        continue_char VARCHAR(10));
DECLARE @temp VARCHAR(10);

insert into @table1(col1)
select 'A' UNION
select 'B' UNION
select 'C' UNION
select 'D' UNION
select 'E' UNION
select 'F' UNION
select 'G';

UPDATE @table1
SET   @temp = CASE WHEN col1 IN ('A','C') THEN col1 ELSE @temp END
     ,continue_char = @temp
OPTION(MAXDOP 1);

SELECT *
FROM @table1;

<强> DBFiddle Demo2