使用循环游标更新表

时间:2012-11-14 09:16:18

标签: sql-server-2008

为了帮助理解我有一个这样的表:

itemcode itemname icode serialnum
1        A        10    0
2        B        10    0
3        C        10    0
4        D        11    0
5        E        13    0
6        F        20    0
7        G        20    0

我希望在循环游标的帮助下使用单个更新查询使结果看起来像下表:

itemcode itemname icode serialnum
1        A        10    1
2        B        10    2
3        C        10    3
4        D        11    1
5        E        13    1
6        F        20    1
7        G        20    2

项目代码是此表中的主键。生成序列号背后的逻辑是每当icode更改时序列号重置为1.如果有人可以帮助解决方案,我需要单个更新查询来在游标的帮助下更新表吗?

2 个答案:

答案 0 :(得分:3)

SQL Fiddle

MS SQL Server 2008架构设置

create table Item
(
  itemcode int,
  itemname char(1),
  icode int,
  serialnum int
)

insert into Item values
(1, 'A', 10, 0),
(2, 'B', 20, 0),
(3, 'C', 11, 0),
(4, 'D', 10, 0),
(5, 'E', 20, 0),
(6, 'F', 10, 0),
(7, 'G', 13, 0)

查询1

update I
set serialnum = rn
from
  (
    select serialnum,
           row_number() over(partition by icode order by itemcode) as rn
    from Item
  ) I

select *
from Item

<强> Results

| ITEMCODE | ITEMNAME | ICODE | SERIALNUM |
-------------------------------------------
|        1 |        A |    10 |         1 |
|        2 |        B |    20 |         1 |
|        3 |        C |    11 |         1 |
|        4 |        D |    10 |         2 |
|        5 |        E |    20 |         2 |
|        6 |        F |    10 |         3 |
|        7 |        G |    13 |         1 |

<强>

更新

使用游标而不是使用游标的版本。

SQL Fiddle

declare @itemcode int
declare @rn int

declare ItemCursor cursor local static forward_only read_only for 
select itemcode,
       row_number() over(partition by icode order by itemcode) as rn
from Item

open ItemCursor

fetch next from ItemCursor
into @itemcode, @rn

while @@fetch_status = 0
begin
  update Item
  set serialnum = @rn
  where itemcode = @itemcode

  fetch next from ItemCursor
  into @itemcode, @rn
end

close ItemCursor
deallocate ItemCursor

答案 1 :(得分:3)

因此,您需要每个icode组的序列号。然后,您可以将ROW_NUMBERPARTITION BY icode

一起使用
WITH CTE AS
(
  SELECT itemcode, itemname, icode, serialnum,
     ,   ROW_NUMBER() OVER (PARTITION BY icode ORDER BY itemcode) AS RN
  FROM dbo.TableName 
)
UPDATE CTE SET serialnum = RN;

如果您希望在每次更新时重新计算它,您可以使用触发器:

CREATE TRIGGER dbo.TableName_Updated
ON dbo.TableName 
FOR UPDATE /* Fire this trigger when one or multiple rows are UPDATEd */
AS BEGIN
    WITH CTE AS
    (
      SELECT itemcode, itemname, icode, serialnum,
         ,   ROW_NUMBER() OVER (PARTITION BY icode ORDER BY itemcode) AS RN
      FROM dbo.TableName t INNER JOIN INSERTED i 
        ON t.itemcode = i.itemcode
    )
    UPDATE CTE SET serialnum = RN
END