SQL Сервер - Избегайте курсора при серийном обновлении - PullRequest
0 голосов
/ 13 января 2020

Как можно избежать использования курсора для реализации следующего? Я читал, что это можно сделать с помощью CTE, но у меня не получилось, чтобы он работал с тем же результатом.

В примере, в котором я использую две таблицы, первая - это таблица holders, содержащая список людей, и таблица передач, где каждая передача указывает на изменение в c записи первой таблицы.

Ниже вы можете увидеть код, который дает правильные результаты:

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

(Правильные) результаты следующие:

Результаты

1 Ответ

0 голосов
/ 13 января 2020

Я думаю, вы просто хотите 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;

Никаких явных циклов не требуется.

...