Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.09.30;
Скачать: CL | DM;

Вниз

Искусственная уникальность в .   Найти похожие ветки 

 
Александр Спелицин ©   (2002-09-10 18:59) [0]

Здравствуйте.
Ситуация с искусственной уникальностью в MSSQL.
Есть таблица: document (doc_id int identity, doc_type int, doc_number int, department_id int, year int, ...).
Номер документа (doc_number) должен быть уникален в пределах заданного отдела (department_id), данного типа (doc_type) и указанного года. Механизм - автоинкремент: максимум + 1.
Т.е. добавление нового документа происходит так:

create procdure CreateFirstTypeDocument @department_id int, @year int, ... какие-то параметры...
as
begin
Declare @doc_nb int
Begin Transaction

-- Точка A

Select @doc_nb = max (doc_number) + 1
From document
Where department_id = @department_id
and year = @year
and doc_type = 1
if @doc_nb Is Null
Select @doc_nb = 1

-- Точка B

Insert document (doc_type, doc_number, department_id, year, ...)
Values (1, @doc_nb, @department_id, @year, ...)

-- Точка C

...
Commit Transaction
end


В таблице одна запись, у которой doc_number = 1. Сервер сильно загружен. Процедуры выполняются медленно.
Теперь из двух сессий одновременно вызывается CreateFirstTypeDocument.
В точке B у для каждой сессии значение @doc_nb будет равно 2. Первая сессия добавляет запись нормально, а вторая своей вставкой нарушает уникальность номеров.

Как обеспечить уникальность?

Заранее спасибо.


 
wicked ©   (2002-09-10 20:49) [1]

если коротко, то код от точки а до точки b просто не нужен...
если тебе нужен id только что вставленной записи, используй системную переменную @@identity...


 
Александр Спелицин ©   (2002-09-10 20:59) [2]

2 wicked:
В том то и дело, что нужен. У каждого подразделения своя нумерация документов. Кроме того, с нового года нумерация вновь начинается с 1.


 
Виталий Панасенко   (2002-09-11 09:53) [3]

По-моему (хотя это тут и критикуют :-))) лучше хранить ИД в отдельной таблице. При этом брать оттуда значение и его же увеличивать на 1. Т.к. начата транзакция, все остальные будут ждать ее окончания и только тогда смогут обновить данные.


 
sniknik ©   (2002-09-11 10:19) [4]

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


 
Zelius ©   (2002-09-11 10:25) [5]

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


 
doomin   (2002-09-11 10:59) [6]

Если для каждого типа и департамента должна быть своя нумерация, то тут без отдельной таблицы с номерами не обойтись, все равно нужно сбрасывать вначале года. Там и сбрасывать. И написать процедуру, которой передается тип и отдел, а она возвращает новый номер (читает из таблицы, инкрементирует и перезаписывает в рамках транзакции). На время работы процедуры (это будет недолго, так как табличка маленькая) лочить табличку для всех. Если другая сессия не смогла получить из-за лока номер, то возвращать -1 например и в основной процедуре вставки документа в цикле ждать номера больше 0. Мне кажется так...



Страницы: 1 вся ветка

Текущий архив: 2002.09.30;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.023 c
14-98309
Неважно...
2002-09-03 18:14
2002.09.30
куда все деваются?


14-98273
AL2002
2002-09-03 11:48
2002.09.30
Может, в рифмы поиграем?


3-98017
IgorP
2002-09-08 17:35
2002.09.30
Компонент TSQLStoredProc не работает с MS SQL и Oracle


14-98293
Сатир
2002-09-03 19:01
2002.09.30
---|Ветка была без названия|---


8-98225
Ден
2002-03-21 20:30
2002.09.30
Как проиграть в своей проге два аудио файла одновременно