![]() |
#1 |
Участник
|
Контроль уникальности с условием dax2012
Есть таблица с полями: ItemId, Status
Status - это Enum, который может принимать значения "Активный", "Неактивный" Есть периодичка, которая обновляет данные в этой таблице, но только среди записей со статусом "Активный". Если записи нет, то создает новую. Тоже со статусом "Активный" Проблема в том, что если будет запущено сразу 2 периодички разными пользователями, то есть риск получить "дубли" Как правило, проблема дублей решается созданием уникального индекса. Но здесь проблема в том, что контролировать уникальность надо не по всем записям, а только среди записей со статусом "Активный" Проверка в триггере смысла не имеет, поскольку именно эта проверка и делается внутри периодички. Новая запись создается именно в случае, когда такой записи не нашли. Значит, скорее всего, и триггер это не поймает Какие есть варианты решения проблемы в dax2012? PS: Вариант запрета запуска периодички по каким-либо условиям - не рассматривается ![]()
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
![]() |
#2 |
Участник
|
А блокировку вешать на таблицу, пока запущенная одним пользователем функция создает эту запись?
|
|
![]() |
#3 |
Участник
|
Цитата:
Если же блокировать в самом начале операции, то это означает запрет выполнения операции вторым пользователем, пока первый не завершит обработку. Специально указал, что такое решение не подходит ![]()
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
![]() |
#4 |
Участник
|
Ну, я не знаю вашей задачи.
Но мне кажется, вы что-то усложняет. Блокируйте перед проверкой "надо создавать или нет", если надо - создавайте и потом сразу разблокируйте. Или у вас такой большой разрыв между проверкой и созданием записи? Почему? |
|
![]() |
#5 |
Участник
|
Т.е. не одну общую транзакцию на всю операцию, а по транзакции на каждую вставку/обновление одной записи в одной таблице?
Нет. Такое решение неприемлемо
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
![]() |
#6 |
Участник
|
Допустим ли для вашей задачи такой сценарий, чтобы запущенные другими пользователями операции смотрели, не запущена ли уже та же операция другим пользователем, и если запущена - то ждали бы пока она завершится, и только тогда начинали свою обработку?
Если это приемлимо - то дальше вы сами знаете как делать. |
|
![]() |
#7 |
Участник
|
Цитата:
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
![]() |
#8 |
Участник
|
Цитата:
По форме вопроса решение выглядит вполне подходящим. Спрашиваю исключительно для своего понимания и интереса. Если не затруднит. |
|
![]() |
#9 |
Участник
|
Ну это же не запрет запуска. Это ожидание. Которое возможно продлится не более нескольких секунд и для пользователя будет не выглядеть запретом.
Могу предложить другой вариант: не апдейтить каждую запись сразу, а сначала собирать записи требующие апдейта в список, и потом одним update recordset все сразу записать. |
|
![]() |
#10 |
NavAx
|
Мне но очень понятна причина таких ограничений. Но можно попробовать поиграться с locks.
Или хакерский подход. Сделать 2 отдельных поля Активный и Неактивный. Тогда получится индекс только по активным. А корректность флажков контролировать через код вставки.
__________________
Isn't it nice when things just work? |
|
![]() |
#11 |
Участник
|
✓Но здесь проблема в том, что контролировать уникальность надо не по всем записям, а только среди записей со статусом "Активный"
Почему не вынести статусы номенклатур в отдельную таблицу типа история статусов? |
|
![]() |
#12 |
северный Будда
|
Так может проще назначить одного уполномоченного и запретить всем остальным?
__________________
С уважением, Вячеслав |
|
![]() |
#13 |
Участник
|
Есть еще простой вариант - сделать пакетное задание, которое будет постоянно искать и удалять дубли. Его разработка займет в десятки раз меньше времени, чем вы УЖЕ ПОТРАТИЛИ на поиск решения.
|
|
![]() |
#14 |
Участник
|
Цитата:
1) Делаете в таблице дополнительное уникальное поле (например копирующее RecId), но заполняете его только для "Неактивных" записей. 2) Включаете это поле в индекс, который должен быть уникальным только для "Активных" записей 3) Делаете этот индекс уникальным для всей таблицы |
|
|
За это сообщение автора поблагодарили: Logger (3), trud (2). |
![]() |
#15 |
Участник
|
2 Kuskov
Много раз так делали и все отлично работает. Более того, для тех записей где доп поле равно нулю можно еще заставить и кеш работать Кстати в уникальное поле удобнее писать не RecId а eventId. Для его выделения есть стандартный статический метод. |
|
![]() |
#16 |
Участник
|
Предложенные варианты
Вкратце поясню. Я не разрабатывал этот бизнес-процесс. Ко мне пришли уже с проблемой, которую надо решить. Любые варианты советов на тему, что Вам надо сам бизнес-процесс менять или организовать его выполнение по другому - заранее обречены. Никто на это не пойдет. Т.е. по сути, выбор стоит между созданием нового поля и удалением "постфактум". На настоящий момент заказчик выбрал вариант удаления "постфактум". Правда, не в отдельной периодичке, а как завершающая операция в этом же процессе, но в отдельной транзакции Если других вариантов решения нет, то на этом можно и закончить. Всех благодарю за участие.
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
![]() |
#17 |
Участник
|
Годится ли то или иное решение - можно сказать только понимая весь бизнес-процесс целиком.
И какой у вас заказчик интересный: не только работает, но и принимает решения в воскресенье.. |
|
![]() |
#18 |
Участник
|
В голову еще приходит SQL filtered unique index:
X++: create table MyTable (a int , b nvarchar(10) , Id int identity(1,1) primary key) CREATE UNIQUE INDEX idx_MyTable_filtered ON MyTable (b) WHERE a = 1 /*Вставилось:*/ insert into MyTable (a,b) values (0, 'AAAA'), (0, 'AAAA'), (0, 'AAAA'), (1, 'BBBB') /*Ошибка:*/ insert into MyTable (a,b) values (1, 'BBBB') |
|
|
За это сообщение автора поблагодарили: gl00mie (5). |
![]() |
#19 |
Участник
|
Цитата:
Просто статусы записываются в отдельную табличку. Некая нормализация скорее. За счёт этого избегаем блокировки при параллельной работе. |
|
![]() |
#20 |
Участник
|
|
|
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|