Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Не обновляется динамический курсор при удалении  [new]
Кесарь
Member

Откуда:
Сообщений: 671
Есть необходимость удалить лишние пересечения из таблицы. В таблицу собраны записи, в которых одно поле должно чётко соответствовать другому - на одну заявку один счёт. Но так как из той базы, откуда это всё берётся, явной привязки счёта к заявке нет, то получается полное пересечение: если у человека в одном фонде два счёта и две заявки, то записей четыре.

Вот представлен кусок кода, который должен это удаление по моему мнению осуществить:

select * from #tmp

declare @old_query_id numeric, @old_lic_acc_no varchar(50)
declare curs cursor DYNAMIC for select * from #tmp order by query_id, lic_acc_no

open curs
fetch curs into @query_id, @lic_acc_no
while @@fetch_status = 0
begin

if @old_query_id = @query_id
begin

delete #tmp where query_id = @query_id and lic_acc_no <> @old_lic_acc_no
delete #tmp where query_id <> @query_id and lic_acc_no = @old_lic_acc_no

select @old_query_id = null, @old_lic_acc_no = null
end
else
select @old_query_id = @query_id, @old_lic_acc_no = @lic_acc_no

fetch curs into @query_id, @lic_acc_no
end
close curs
deallocate curs

select * from #tmp

На входе в курсор в таблице находится 10 записей:

№ query_id lic_acc_no
---------------------------------------------
1 40000000000015046 LP0449
2 40000000000037662 LP1928
3 40000000000174203 LP6419
4 40000000000174212 LP6417
5 40000000000174220 LP6421
6 40000000000174233 LP6416
7 40000000000174233 LP6953

8 40000000000180523 LP6632
9 40000000000187586 LP6416
10 40000000000187586 LP6953


Необходимо на выходе получить 8

№ query_id lic_acc_no
---------------------------------------------
1 40000000000015046 LP0449
2 40000000000037662 LP1928
3 40000000000174203 LP6419
4 40000000000174212 LP6417
5 40000000000174220 LP6421
6 40000000000174233 LP6416
7 удалена
8 40000000000180523 LP6632
9 удалена
10 40000000000187586 LP6953

А получаю 6! После отслеживания процесса увидел, что курсор живёт отдельно от таблицы: второй раз условие отрабатывает так, как будто первого удаления не было.

Почему курсор не обновляется, хотя он объявлен динамическим?
4 апр 12, 19:26    [12366959]     Ответить | Цитировать Сообщить модератору
 Re: Не обновляется динамический курсор при удалении  [new]
Knyazev Alexey
Member

Откуда: Екб -> Мск
Сообщений: 10233
Блог
а нафиг тут вообще курсор?

with cte
as
(
select row_number() over ( partition by query_id, lic_acc_no order by []  ) id from #tmp
)
delete from cte where id > 1
4 апр 12, 19:47    [12367084]     Ответить | Цитировать Сообщить модератору
 Re: Не обновляется динамический курсор при удалении  [new]
Glory
Member

Откуда:
Сообщений: 104751
Кесарь
Почему курсор не обновляется, хотя он объявлен динамическим?

Это необходимое условие, но недостаточное
Как серверу отслеживать изменения, если у вашей таблицы наверняка нет ПК
4 апр 12, 19:56    [12367112]     Ответить | Цитировать Сообщить модератору
 Re: Не обновляется динамический курсор при удалении  [new]
invm
Member

Откуда: Москва
Сообщений: 9824
declare @t table (query_id numeric, lic_acc_no varchar(50));

insert into @t
values
 (40000000000015046, 'LP0449'),
 (40000000000037662, 'LP1928'),
 (40000000000174203, 'LP6419'),
 (40000000000174212, 'LP6417'),
 (40000000000174220, 'LP6421'),
 (40000000000174233, 'LP6416'),
 (40000000000174233, 'LP6953'),
 (40000000000180523, 'LP6632'),
 (40000000000187586, 'LP6416'),
 (40000000000187586, 'LP6953');
 
with x(n1, n2) as
(
 select
  row_number() over (partition by lic_acc_no order by query_id),
  row_number() over (partition by query_id order by lic_acc_no)
 from
  @t
)
delete x where n1 <> n2;

select * from @t order by query_id;
4 апр 12, 20:23    [12367250]     Ответить | Цитировать Сообщить модератору
 Re: Не обновляется динамический курсор при удалении  [new]
Кесарь
Member

Откуда:
Сообщений: 671
Спасибо всем, помогло и так, и так.

Касательно конструкции

with x(n1, n2) as
(
select
row_number() over (partition by lic_acc_no order by query_id),
row_number() over (partition by query_id order by lic_acc_no)
from
@t
)
delete x where n1 <> n2;

- век живи, век учись :) я что-то такое думал через селект сделать, но не знал как.
5 апр 12, 11:56    [12369545]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить