powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Курсор FOR UPDATE OF.... не объевляется
8 сообщений из 8, страница 1 из 1
Курсор FOR UPDATE OF.... не объевляется
    #32030848
Query
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хочу убить двойные записи некоторые. Решил сначала пройтись курсором и выставить признак в NULL, а потом просто убить все эти NULL разом.
Сделал хранимую процедуру

CREATE PROCEDURE [dbo].[drop_worker_data_double] AS

DECLARE @ErrNum integer,
@OBJ_ID_ID decimal(38,0),
@OLD_OBJ_ID_ID decimal(38,0),
@YEAR_DATA varchar(4),
@OLD_YEAR_DATA varchar(4),
@DATEEVENT datetime,
@OLD_DATEEVENT datetime,
@STAY_IN decimal(1,0)

DECLARE Worker_Curs CURSOR
LOCAL FORWARD_ONLY DYNAMIC SCROLL_LOCKS TYPE_WARNING
FOR SELECT OBJ_ID_ID, YEAR_DATA, DATEEVENT, STAY_IN
FROM [dbo].[F_T_WORKER_CNT]
ORDER BY OBJ_ID_ID ASC, YEAR_DATA ASC, DATEEVENT DESC
FOR UPDATE OF STAY_IN

SET NOCOUNT ON
BEGIN TRANSACTION Drop_Worker_Data_Double

-- открываем курсор
OPEN Worker_Curs

-- вытаскиваем из него первую строчку
FETCH NEXT FROM Worker_Curs INTO @OLD_OBJ_ID_ID, @OLD_YEAR_DATA, @OLD_DATEEVENT, @STAY_IN

-- теперь пошли перебор и сравнение
WHILE @@FETCH_STATUS = 0
BEGIN
-- вытащили следующую запись
FETCH NEXT FROM Worker_Curs INTO @OBJ_ID_ID, @YEAR_DATA, @DATEEVENT, @STAY_IN
-- если ID равны, то это один и тот же объект
IF @OBJ_ID_ID = @OLD_OBJ_ID_ID
BEGIN
-- если годы равны???
IF @OLD_YEAR_DATA = @YEAR_DATA
BEGIN
IF @OLD_DATEEVENT = @DATEEVENT
-- пометим эту запись
UPDATE [dbo].[F_T_WORKER_CNT] SET STAY_IN = NULL
WHERE CURRENT OF Worker_Curs

SET @ErrNum = @@ERROR
IF @ErrNum <> 0
GOTO RollBackTran
ELSE
-- запомним дату поступления данных
SET @OLD_DATEEVENT = @DATEEVENT
END
ELSE
-- заменим старый год
SET @OLD_YEAR_DATA = @YEAR_DATA
END
ELSE
BEGIN
SET @OLD_OBJ_ID_ID = @OBJ_ID_ID
SET @OLD_YEAR_DATA = @YEAR_DATA
SET @OLD_DATEEVENT = @DATEEVENT
END
END

CLOSE Worker_Curs
DEALLOCATE Worker_Curs

COMMIT TRANSACTION Drop_Worker_Data_Double
GOTO ReturnRezult

RollBackTran:
CLOSE Worker_Curs
DEALLOCATE Worker_Curs

ROLLBACK TRANSACTION Drop_Worker_Data_Double
RAISERROR ('Clear doubles failed from ais_drop_ul_worker_data_double',1,1)

ReturnRezult:
RETURN 0
GO

И в отладчике валится, и при запуске. Ругается на то, что курсор объявлен как READ_ONLY и его UPDATE-ить нельзя.
Как курсор объявить, чтобы он работал с UPDATE? А то весь MSDN перерыл по ключевым словам, а там примеров то и нету
.
...
Рейтинг: 0 / 0
Курсор FOR UPDATE OF.... не объевляется
    #32030849
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL не FoxPro и такие фокусы заканчиваються всегда печально. Не будь в обиду, но сейчас надаю кучу советов:

1. Создать уникальный индекс по полям. Тогда больше никаких проблем с дублированием записей не возникнет

2. Стараться всегда все делать через команды SQL, не использовать курсоры для простого перелопачивания и уж тем более изменения
записей. Для этого использовать UPDATE и DELETE

3. Если у таблицы нет Primary Key, то создать его, тогда можно выполнить следующий запрос (в нем для примера как PK я использовал поле id int not null primary key):

delete d
from F_T_WORKER_CNT d
inner join
(select t1.id
from F_T_WORKER_CNT t1
inner join
(select OBJ_ID_ID, YEAR_DATA, DATEEVENT
from F_T_WORKER_CNT
group by OBJ_ID_ID, YEAR_DATA, DATEEVENT
having Count(*) > 1) as t2 on t1.OBJ_ID_ID = t2.OBJ_ID_ID and
t1.YEAR_DATA = t2.YEAR_DATA and
t1.DATEEVENT = t2.DATEEVENT
where not t1.id in (select Min(tx1.id)
from F_T_WORKER_CNT tx1
inner join
(select OBJ_ID_ID, YEAR_DATA, DATEEVENT
from F_T_WORKER_CNT
group by OBJ_ID_ID, YEAR_DATA, DATEEVENT
having Count(*) > 1) as tx2 on tx1.OBJ_ID_ID = tx2.OBJ_ID_ID and
tx1.YEAR_DATA = tx2.YEAR_DATA and
tx1.DATEEVENT = tx2.DATEEVENT
where tx1.OBJ_ID_ID = t1.OBJ_ID_ID and
tx1.YEAR_DATA = t1.YEAR_DATA and
tx1.DATEEVENT = t1.DATEEVENT)) as t on d.Id = t.Id

По идее должно сработать, хотя наверное при желании скрипт можно соптимизировать и написать более красиво.

4. Если PK нет, и создать его не предстовляеться возможности, то вариант остается только такой:

create table #F_T_WORKER_CNT (OBJ_ID_ID decimal(38, 0) not null, YEAR_DATA varchar(4) not null, DATEEVENT datetime not null)

insert into #F_T_WORKER_CNT (OBJ_ID_ID, YEAR_DATA, DATEEVENT)
select OBJ_ID_ID, YEAR_DATA, DATEEVENT
from F_T_WORKER_CNT
group by OBJ_ID_ID, YEAR_DATA, DATEEVENT
having Count(*) > 1

delete d
from F_T_WORKER_CNT d
inner join
(select OBJ_ID_ID, YEAR_DATA, DATEEVENT
from F_T_WORKER_CNT
group by OBJ_ID_ID, YEAR_DATA, DATEEVENT
having Count(*) > 1) as t on d.OBJ_ID_ID = t.OBJ_ID_ID and
d.YEAR_DATA = t.YEAR_DATA and
d.DATEEVENT = t.DATEEVENT

insert into F_T_WORKER_CNT (OBJ_ID_ID, YEAR_DATA, DATEEVENT)
select OBJ_ID_ID, YEAR_DATA, DATEEVENT
from #F_T_WORKER_CNT

drop table #F_T_WORKER_CNT

Получается, что мы сохраняем повторяющиеся записи как уникальные во временную таблицу, удаляем их с таблицы и переносим с временной обратно.

Кстати - если не секрет, что храниться в поле OBJ_ID_ID, имеющего тип аж decimal(38, 0) ?
...
Рейтинг: 0 / 0
Курсор FOR UPDATE OF.... не объевляется
    #32030850
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Черт, чего же все отсутпы то сьела ?
...
Рейтинг: 0 / 0
Курсор FOR UPDATE OF.... не объевляется
    #32030851
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Черт, чего же все отступы то сьела ?
...
Рейтинг: 0 / 0
Курсор FOR UPDATE OF.... не объевляется
    #32030852
Фотография jimmers
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго времени суток

2Query: Возможно, Вам будут интересны следующие статьи:

http://www.swynk.com/friends/boyle/removeduplicate.asp
http://www.sqlteam.com/item.asp?ItemID=3331

2ASCRUS: Вариант 4 не учитывает наличия полей кроме OBJ_ID_ID, YEAR_DATA, DATEEVENT.

Удачи
...
Рейтинг: 0 / 0
Курсор FOR UPDATE OF.... не объевляется
    #32030876
Query
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, дальше разберусь. Я же не виноват, что такие данные приходят
.
...
Рейтинг: 0 / 0
Курсор FOR UPDATE OF.... не объевляется
    #32030878
Ольга
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть хорошее слово DISTINCT
BOL:The DISTINCT keyword eliminates duplicate rows from the results of a SELECT statement.
...
Рейтинг: 0 / 0
Курсор FOR UPDATE OF.... не объевляется
    #32030898
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ольга права - если даные приходят извне, то лучше их сразу перегонять в свою структуру обработанными.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Курсор FOR UPDATE OF.... не объевляется
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]