|
|
#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 |
|
Участник
|
|
|
|
|
|
| Опции темы | Поиск в этой теме |
| Опции просмотра | |
|