【问题标题】:SQL Server - Avoid cursor while serial updateSQL Server - 串行更新时避免光标
【发布时间】:2020-01-13 16:58:11
【问题描述】:

如何避免使用游标来实现以下内容?我读到它可以用 CTE 完成,但我没有得到相同的结果。

在示例中,我使用了两个表,第一个是 holder 表,其中包含人员列表,以及 transfer 表,其中每次转移都指示第一个表的特定记录的更改。

您可以在下面看到代码,它带来了正确的结果:

create table #holders(Person VARCHAR(50), Kind VARCHAR(50), Pctg FLOAT)
create table #transfers(Person_FROM VARCHAR(50), Person_To VARCHAR(50), Kind VARCHAR(50), Pctg_New FLOAT, Eff_Date DATE)

insert into #holders
select 'Person One', 'Kind 1', 50 union all
select 'Person Two', 'Kind 1', 50 union all
select 'Person Three', 'Kind 1', NULL union all
select 'Person Four', 'Kind 1', NULL union all
select 'Person One', 'Kind 2', 100

insert into #transfers
select 'Person One', 'Person A', 'Kind 1', 70, '2019-12-31' union all
select 'Person Two', 'Person B', 'Kind 1', 30, '2020-01-01' union all
select 'Person A', 'Person A1', 'Kind 1', 70, '2020-01-02' union all
select 'Person A', 'Person A2', 'Kind 1', 70, '2020-01-03' union all --Should Avoided
select 'Person A2', 'Person A3', 'Kind 1', 70, '2020-01-04' union all --Should Avoided
select 'Person A1', 'Person A4', 'Kind 1', 70, '2020-01-05' 

declare
    @Person_FROM        varchar(50),
    @Person_To          varchar(50),
    @Kind               varchar(50),
    @Pctg_New           float

declare cur cursor for select Person_FROM, Person_To, Kind, Pctg_New from #transfers order by Eff_Date
open cur
fetch next from cur into @Person_FROM, @Person_To, @Kind, @Pctg_New
while @@FETCH_STATUS = 0 begin
    update #holders set Person = @Person_To, Pctg = @Pctg_New where Person = @Person_FROM AND Kind = @Kind
    fetch next from cur into @Person_FROM, @Person_To, @Kind, @Pctg_New
end
close cur
deallocate cur

SELECT * FROM #holders

drop table #holders
drop table #transfers

(正确的)结果如下:

Results

【问题讨论】:

  • 这只是为了学习吗?我只问了一个非常相似的问题:stackoverflow.com/questions/46153033/…
  • 嗨列奥尼达,感谢您的评论。我认为实际上并非如此,因为这里需要对更新进行序列化(例如:“Person One”->“Person A”->“Person A1”->“Person A1”->“人 A4")

标签: sql-server serialization sql-update cursor common-table-expression


【解决方案1】:

我想你只是想要update/join:

update h
     set Person = t.Person_To,
         Pctg = t/Pctg_New 
from #holders h join
     #transfers t
     on h.person = t.person_from and h.kind = t.kind;

不需要显式循环。

【讨论】:

  • 嗨@Gordon Linoff,感谢您的回答。使用光标逐行的(正确)结果是:“A4 人”、“B 人”、“3 人”、“4 人”和“1 人”。使用此更新查询,除第一个之外的所有人员的结果都相似:具体而言:“人员 A”、“人员 B”、“人员三”、“人员四”和“人员一”。我认为问题在于它需要序列化更新(按 Eff_Date 排序)和某种递归(第一行应使用此流程更新 4 次:“Person One”->“Person A”->“Person A1 " --> "A1 人" --> "A4 人")。
  • @SteliosBobolakis 。 . .您不需要光标,最好不要使用。
  • 我同意,但结果不一样!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
  • 1970-01-01
  • 2017-03-18
相关资源
最近更新 更多