2

为了帮助理解,我有一张这样的表格:

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。如果有人可以提供解决方案,我需要一个更新查询来借助游标更新表?

4

2 回答 2

3

SQL小提琴

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

结果

| 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小提琴

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
于 2012-11-14T09:22:18.263 回答
3

因此,您需要每个 icode 组的序列号。然后你可以ROW_NUMBER使用PARTITION 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
于 2012-11-14T09:24:02.260 回答