Имя: Пароль:
1C
1C 7.7
v7: Как обеспечить уникальность поля?
,
0 PZh
 
10.11.11
10:31
Ведь проверка уникальности в процедуре ПриЗаписи() не дает 100% гарантии.
1 ado
 
10.11.11
10:35
Чо?
2 PZh
 
10.11.11
10:36
В справочнике автоматом блюдется уникальность кода. Если требуется блюсти уникальность не одного кода, а кода и чего-то еще, то как быть?
3 Ёпрст
 
10.11.11
10:38
(2) блюсти вестимо самому
4 Mikeware
 
10.11.11
10:38
проверять
5 PZh
 
10.11.11
10:43
(3) Как?
6 Ёпрст
 
10.11.11
10:47
(5) см. (4)
7 rs_trade
 
10.11.11
10:48
(5) Хм... Наверное попытаться найти элемент с таким же значением реквизита. Нет?
8 PZh
 
10.11.11
10:49
(6) гениально.

Вы первый пост читали?
Я умею только при записи проверять.
9 ДенисЧ
 
10.11.11
10:49
Телепатирую - автор хочет отловить все возможности. А ПриЗаписи() при программном не работает...
10 Ёпрст
 
10.11.11
10:51
(9) врят ли, он даже в приЗаписи не может обеспечить уникальность.. куда уж там до программной записи.
11 PZh
 
10.11.11
10:52
(9)
При программном как раз проблем меньше, если через транзакцию сначала заблокировать весь справочник, потом проверить, а потом записать.
12 ado
 
10.11.11
10:52
(9) А при программном надо проверять в программе. И делать это в транзакции.
13 Ёпрст
 
10.11.11
10:52
(0) самое тупое - либо элемент справочника, либо константа. Блокируется и то и то, если что, программно.
14 ado
 
10.11.11
11:00
(13) Кстати, а как константу программно блокировать?
15 Ёпрст
 
10.11.11
11:02
(14)токма всю табличку целиком..
16 PZh
 
10.11.11
11:03
(13) Чо?

+ Если в ПриЗаписи открыть транзакцию и отменить прям перед "КонецПроцедуры" или вообще не отменять, то пауза между ее откатом и непосредственном началом записи в БД будет?
17 ЧеловекДуши
 
10.11.11
11:03
(11)1С это не ваше...
18 ЧеловекДуши
 
10.11.11
11:04
(16)При записи идеть Глобальная транзакция на всю БД. Так работает 1С.
Транзакция длится столько времени, сколько отрабатывает функция "ПриЗаписи"
19 Ёпрст
 
10.11.11
11:05
(18) че за бред то ? Никакой транзакции в ПриЗаписи нет
20 ЧеловекДуши
 
10.11.11
11:05
+(16)Все проверки в функции "ПриЗаписи" снижают производительность всей БД. Особенно это заметно при многопользовательском доступе к БД.
21 ЧеловекДуши
 
10.11.11
11:06
(19)Да ну... Куда оно делась?
Автор (0) в диалоге выполняет запись документа или Справочника.
22 ЧеловекДуши
 
10.11.11
11:07
+(19)Мы щас про 7.7...
23 Ёпрст
 
10.11.11
11:07
(16) ёпта, у справочника есть метод Блокировка, если че..
создаешь элемент, пытаешься заблокировать его, если успешно - меняешь реквизит в нём с уникальным значением. Всё.

Если константа - блокируешь всю табличку констант целиком в НачатьТранзакцию ..
24 Ёпрст
 
10.11.11
11:07
(21) никуда, её никогда нет и не было.
25 ЧеловекДуши
 
10.11.11
11:08
(23)А у документа оно тоже есть?
НачатьТранзакцию  в функции ПриЗаписи отрабатывает автоматом.
26 PZh
 
10.11.11
11:09
(23) Какая блокировка? Мне не элемент надо заблокировать, а удостовериться что никто не нарожает аналогичных записей!
27 ЧеловекДуши
 
10.11.11
11:09
(24)Ну... останемся каждый при своем.
Автор (0) все ровно все узнает на собственной шкурке.
28 ado
 
10.11.11
11:09
(15) Вот то-то и оно. Это невкусно.

(13) Будет.

Сделай служебный справочник с одним элементом. В нем храни счетчик для своего уникального реквизита. При записи блокируй программно этот элемент, устанавливай реквизизит, инкрементируй счетчик. Перректально, конечно, а шо поделать ...
29 Ёпрст
 
10.11.11
11:09
+24 Транзакция есть только при проведении дока, при этом блокируется табличка шапки и ТЧ дока + регистры, которые участвуют в движениях дока..+таблички справочника и другие, если к ним было обращение.
30 Ёпрст
 
10.11.11
11:10
(26) ты просто не догоняешь.
31 ЧеловекДуши
 
10.11.11
11:10
(29)Ты уверен?... :)
Я уже устал удивляться фокусам 7.7, так что для меня все едино :)
32 Ёпрст
 
10.11.11
11:11
(31) rtfm
33 ЧеловекДуши
 
10.11.11
11:11
(26)Автоматом можно контролировать только КОД.
Все остальные реквизиты контролируешь ты сам.
Вероятность появления дубля = 40% :)
34 Mikeware
 
10.11.11
11:11
(29) Журнал забыл!
И систем, если в учете учствует
35 ЧеловекДуши
 
10.11.11
11:12
(32)Грубиян :)
36 Ёпрст
 
10.11.11
11:12
(34) да, он в первую очередь..
37 ado
 
10.11.11
11:12
(32) В том то и проблема, что fm про это скромно молчит. Нету по 7-ке аналога "Проф. разработки".
38 Ёпрст
 
10.11.11
11:13
(33) брехня.
МОД работает на блокировке таблички констант, за годы ни единого дубля.
39 Ёпрст
 
10.11.11
11:14
(37) ну знаешь, открыть профайлер или провести мини-эксперимент на 2-х пользователях, пару минут на всё.
40 Mikeware
 
10.11.11
11:14
(37) Видимо, разрабатывают не профессионалы...
правда, не следует забывать, чт ковчеег был построен любителем, а титаник - порфессионалами...
41 ЧеловекДуши
 
10.11.11
11:14
(38)Мы не про МОД... Забудь ты про МОД... Он платный ;)
42 Mikeware
 
10.11.11
11:14
(41) он как раз про принцип
43 ЧеловекДуши
 
10.11.11
11:14
+(38)Мне не нравится МОД :)
44 ЧеловекДуши
 
10.11.11
11:15
(42)Про какой принцип?
Автор не хочет делать уникальность по Коду.
Ему нужен реквизит.
Вероятность дубля будет всегда.
45 ado
 
10.11.11
11:15
(41) А что мешает воспользоваться аналогичными приемами? МОД с тебя за это роялти потребует?
46 ЧеловекДуши
 
10.11.11
11:16
+(42)Но маленькая.
(0)Нужно добавить реквизит с отбором и все.
47 Ёпрст
 
10.11.11
11:16
(44) ну и с чего будут дубли по-твоему ?
48 ado
 
10.11.11
11:17
(44) Вот в (28) один из приемов обеспечения уникальности произвольного реквизита. Почему он не должен работать?
49 Mikeware
 
10.11.11
11:18
В общем-то, можно еще гуид генерить....
50 ЧеловекДуши
 
10.11.11
11:20
(47)в 1С даже изредка дублируется ИД...
(48)Громоздко. :)
51 ado
 
10.11.11
11:20
(49) Часто бывает нужна нумерация в каком-то конкретном формате.
52 PZh
 
10.11.11
11:21
Короче, если без дополнительного справочника, то ПриЗаписи() нужно записывать явно - программно через транзакцию с блокировкой всей таблицы справочника.

(30) Я действительно не догоняю, объясни пожалуйста при чем здесь "Блокировка()"???
53 ado
 
10.11.11
11:21
(50) Громоздко, но возможно ведь.
54 ado
 
10.11.11
11:23
(52) Проблема в том, что сама запись у тебя в эту транзакцию не войдет. Следовательно, никакой гарантии ты не получишь.
55 ЧеловекДуши
 
10.11.11
11:23
(52)Таблица и без этого в транзакции.
Не нужно явно объявлять транзакцию.

(53)Конечно, можно пойти дальше и на следующий подчиненный справочник сделать ставку уникальности :)
56 PZh
 
10.11.11
11:24
(54) Почему? Второй раз записывается - тоже самое что и первый, так что гарантия - 100%
57 PZh
 
10.11.11
11:25
(55) Товарищ, верь! Никакой транзакции в процедуре ПриЗаписи() нет и не было! Это процедура выполняется перед непосредственной записью по правилам по которым выполняется любая другая процедура модуля!
58 ЧеловекДуши
 
10.11.11
11:25
(56)Ты уверен, что мы об одном и том же? ;)
Ты учел еще 10 (ну второго) пользователей, которые будут стараться записать данные в этот же справочник
59 PZh
 
10.11.11
11:29
(58) Да учел.
Таблица блокируется, потом выполняется проверка, потом запись. Значение - точно уникально и уже записано в БД, после окончания процедуры ПриЗаписи() это значение без изменений записывается повторно, но это никак не влияет на других пользователей, т.к. они уже видят это значение при своих проверках.
60 Ёпрст
 
10.11.11
11:29
(52) при том, что будет заблокирован только 1 элемент, а не вся табличка + заблокированный элемент только 1 пользователь может изменить.
61 Ёпрст
 
10.11.11
11:30
(59) не нужна там транзакция и блокировать целиком всю табличку - моветон.
62 ado
 
10.11.11
11:31
(56) Хммммм ....
63 ado
 
10.11.11
11:34
(61) Ой, да ладно, на фоне того феерического пи*деца, который происходит при проведении документа, это уже никак не может испортить красоту картины мироздания.
64 BlackSeaCat
 
10.11.11
11:34
А код, сформированный из системных даты+времени с уникальным префиксом для каждого пользователя - моветон или куда?
65 ado
 
10.11.11
11:35
(62) Черт, а я ведь делал то же самое в одном из своих решений, и сам забыл уже.
66 ado
 
10.11.11
11:36
(64) Смотри (51)
67 xazrad
 
10.11.11
11:37
(0) посмотри штрихкод в ТИС по нему соблюдается уникальность
68 BlackSeaCat
 
10.11.11
11:38
(66) Это уже телепание: ТС не озвучил ВСЕ свои условия.
69 ado
 
10.11.11
11:39
(68) Дык, Миста всегда была рингом для битвы телепатов :-)
70 BlackSeaCat
 
10.11.11
11:42
(68) Звыняйте, я тут недавно. И не собираюсь вступать в битву. Так что успехов всем участникам забега!
71 trad
 
10.11.11
11:44
Всю ветку не читал, но может быть автору пригодится.

В модуле формы справочника номенклатура:
Процедура ПриЗаписи()
   Если Выбран()=0 Тогда
       //при записи нового элемента назначаем новый код с заполнением "дыр"
       рс=СоздатьОбъект("ODBCRecordset");
       рс.ВыполнитьИнструкцию("
       |set implicit_transactions on
       |exec _1sp_"+рс.мд.ИмяТаблицыСправочника("Номенклатура")+"_TLockX
       |");
       ТекстЗапроса="
       |declare @code int, @cur_code int
       |set @cur_code = 0
       |declare findcode cursor local fast_forward read_only
       |for select cast(code as int) from $Справочник.Номенклатура (nolock) order by code
       |
       |open findcode
       |fetch next from findcode into @code
       |while @@fetch_status = 0
       |begin
       |  if @cur_code+1 < @code
       |    break
       |  set @cur_code = @code
       |  fetch next from findcode into @code
       |end
       |close findcode
       |select @cur_code+1
       |";
       Код=рс.ВыполнитьСкалярный(ТекстЗапроса);
   КонецЕсли;

КонецПроцедуры    // ПриЗаписи

работает как часы
72 PZh
 
10.11.11
14:00
(71) Это немного не в тему...
Но я по умничаю, с вашего позволения. А не легче так, без всяких курсоров? Я думаю это будет сильно быстрее вашего кода.


Процедура ПриЗаписи()
   Если Выбран()=0 Тогда
       //при записи нового элемента назначаем новый код с заполнением "дыр"

       рс=СоздатьОбъект("ODBCRecordset");
       рс.ВыполнитьИнструкцию("
       |set implicit_transactions on
       |exec _1sp_"+рс.мд.ИмяТаблицыСправочника("Номенклатура")+"_TLockX
       |");
       ТекстЗапроса="
       |SELECT min(cast(code as int)) + 1
       |    FROM $Справочник.Номенклатура (nolock)
       |    WHERE cast(code as int) + 1 not in (SELECT cast(code as int) FROM $Справочник.Номенклатура)
       |";
       Код=рс.ВыполнитьСкалярный(ТекстЗапроса);
   КонецЕсли;

КонецПроцедуры    // ПриЗаписи
73 trad
 
11.11.11
09:01
(72)
да, точно быстрее
спасибо!
Компьютеры — прекрасное средство для решения проблем, которых до их появления не было.