Удав написал(а):
abap написал:
Рассмотрим ключ, состоящий из 4-х полей, например: WERKS, LGORT, MJAHR и наш ID.
Вопросы: 1. При чем тут NRIV, если я просто хочу увеличить суррогатный ключ ID на единичку? 2. Какие будут тормоза при определени max( ID ), если указать остальную часть ключа? 3. Как обойтись в системе, в которой работает больше одного пользователя без блокировок?
1.При одновременном обращении к select`у возможно появление 2-х одинаковых номеров. Что, соответственно, ведет к дампу при попытке вставки записи в таблицу.
2.см. п.3 - для правильного определения последнего номера необходимо блокировать ВСЮ часть таблицы по 3-м первым полям. Соответственно, если работает не один человек, то при получении номера он вынужден ждать, пока не снимется блокировка.
3. Если речь идет о получении нового номера, то с помощью механизма, предлагаемого SAP, который называется "Объекты нумерации". :wink:
Почитайте первоисточник.
Вещь базовая, поэтому важно полное понимание.
Рассмотрим вопрос более детально.
Итак, предлагался ключ: год/завод/склад/ID. Для связи с жизнью предположим, что мы хотим пишем модуль по созданию неких внутренних складских документов – назовем их Актами. Предположим далее, что у нас 10 заводов по 10 складов на каждом:
Завод 5000 Склад 5001, 5002, …, 5010
Завод 5100 Склад 5101, 5102, …, 5110
…
Завод 5900 Склад 5901, 5902, …, 5910
Воспользуемся нумератором и создадим последовательно (для простоты) по два Акта на каждом складе. Получим записи в нашей таблице (например, Z_TABLE)
с ключами (мандант не рассматриваем):
2007 5000 5001 0000000001
2007 5000 5001 0000000002
2007 5000 5002 0000000003
2007 5000 5002 0000000003
…
2007 5900 5910 0000000199
2007 5900 5910 0000000200
Вместо этого хотели:
2007 5000 5001 0000000001
2007 5000 5001 0000000002
2007 5000 5002 0000000001
2007 5000 5002 0000000002
…
2007 5900 5910 0000000001
2007 5900 5910 0000000002
Даже использование в качестве subobject в function 'NUMBER_GET_NEXT', например, завода все равно проблему не решит, т.е. придется либо создавать по одному нумератору на завод либо мириться с «рваной» нумерацией на складе. (Правда, возможно, прокатит создать и использовать в качестве subobject 8-ми-байтный домен, в качестве значения которого брать конкатенацию завода/склада – не знаю, сам не пробовал).
Далее. Предположим, создается очередной Акт, на заводе 5900/ складе 5910. Ну и что криминального в том, что перед получением очередного номера(ID) на этом складе, мы заблокируем запись по ключу 2007 5900 5910 ? Как говорится, в этом нет никакого вреда, кроме пользы. Для этого технология блокирования и существует.
Более того. Предположим даже такой вариант, что мы поставлены в условия, когда блокировать склад недопустимо (например, кладовщик Вася имеет привычку открывать транзакцию создания Акта и уходить на перекур, а кладовщик Петя сильно нервничает в этот момент при виде сообщения: «Запрошенный объект сейчас блокирован пользователем Васей»). В этом случае наши действия меняются совсем незначительно: получаем следующий ID (max по году/заводу/складу); ставим блокировку по полному ключу (году/заводу/складу/maxID+1); селектим еще раз таблицу по году/заводу/складу/maxID+1 в качестве лекарства от дампов, далее делаем свой INSERT;
далее снимаем блокировку.
Именно такая технология используется, например, в многострадальной SAPMF05A, где кстати в силу простоты ключа используется именно нумератор (RF_BELEG). Заглянем в ФМ ‘RF_GET_DOCUMENT_NUMBER’. Видим, что после получения очередного номера по БЕ в качестве subobject, могучие программисты SAP все-таки делают проверку на существование записи с таким ключом в BKPF. Интересно зачем? Ах да, о чем это я... Да вот же и ответ!
Code:
*------- Beleg probelesen ----------------------------------------------
select single belnr into bkpf-belnr from bkpf
where bukrs = company
and belnr = document_number
and gjahr = year.
if sy-subrc is initial.
*
* Belegnummer & & & wurde bereits vergeben
*
message a152 with company document_number year
range "Note449030
raising duplicate_number.
endif.
что в переводе с ломанного немецкого: "oops, а номерок уже использован - поэтому ABEND". Подумаешь, юзер перед этим долбил 20 позиций в документ...
Вот тебе и SAP best practices..