Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2002.09.30;
Скачать: [xml.tar.bz2];

Вниз

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

 
Александр Спелицин   (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;
Скачать: [xml.tar.bz2];

Наверх





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


1-98167
kex86
2002-09-16 01:48
2002.09.30
KbLayout


14-98320
France
2002-09-05 10:01
2002.09.30
Странности с помощью в Делфи 6


4-98393
oduvan
2002-08-13 19:37
2002.09.30
Проблема при подаче сообщения WM_COPYDATA из формы в форму.


1-98183
Андрусь
2002-09-17 20:19
2002.09.30
откуда пришёл фокус





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский