powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Уникальный индекс номера записи
30 сообщений из 30, показаны все 2 страниц
Уникальный индекс номера записи
    #32441343
Muric
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброе утро!
Ситуация такая:
В одном методе у меня согласно признаку (редактирования или добавления записи) происходят эти действия. Сначала у меня при добавлении новой записи была инструкция INSERT только для тех полей, где проверяется целостность базы данных, а зетем шел REPLACE. Когда попробовал это действие по сети, то у меня возникли существенные задержки при добавлении новой записи. Я убрал REPLACE и в инструкцию INSERT поместил изменения всех значений полей. Результат был потрясающим. Но проблема была в том, что помимо INSERT необходимо делать и просто обнавление данных. В обновлении данных у меня по-прежнему участвует REPLACE. Может быть использовать UPDATE? Тогда необходимо иcпользовать уникальный индекс номера записи. Есть ли в VFP6 возможность автоматического добавления уникального номера записи или необходимо самому создать такое поле? Если самому создавать такое поле, то как присваивать номер для записи, т.е. по RECNO() записи или как-то по-другому?
Буду благодарен за советы!
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32441421
Фотография Hel!Riser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
такое поле создавать нужно ручками. И в VFP60 пользовать свою ф-цию создания уникального ключа. Афтоинкремент появися в 8 версии. Лична я еще с FPD26 пользую данную мульку на ключ. Выдрал с какой-то книжки и модифил. См. комменты
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
************* FUNCTION NewID
*****************************************************************************
* Описание	:	Создание суррогатного первичного ключа в  36 -ричной
*				системе исчисления символьного типа.
* Необходимо:	Таблица SYSTEM со структурой TagName (C10) ASC; UPPER,
*				Value (C{самое_длинное_ключевое_поле_в_БД})
*				Значение ключа - существующее значение поля SYSTEM.VALUE
*               Таблица system остается открытой
* Параметры	:	Псевдоним таблицы, для которой генерируется ключ.
*				Если параметр опущен - генерируется ключ для текущей таблицы
* Возрат	: 	lcID {символьное значение}
* Автор		:	Денис В. Степанов, ООО  "Инфогруппа ЦТУ" 
*				г. Нижний Новгород, ул. Васенко, 4 , ком.  34 
*****************************************************************************
* ----------------------------------------------------------------------------
 
* Внесены изменения:
* В БД system добавлено поле TYPE
* если оно равно  "HEX"  вызывается процедура генерации  36 -ричного ключа
* если оно равно  "DEC"  вызывается процедура генерации целого ключа  "counter" 
* если оно равно  "STR"  вызывается процедура генерации  10 -ричного ключа
*
PARAMETER tcAlias, tcSystemAlias

#IF  "2 . 6 "$VERSION()
	PRIVATE lcAlias, lcID, lcOldReprocess, lnOldArea, lnID, lnSec
#ELSE
	LOCAL lcAlias, lcID, lcOldReprocess, lnOldArea, lnID, lnSec
#ENDIF

lnOldArea=SELECT()

IF PARAMETERS()< 1 
	lcAlias=UPPER(ALIAS())
ELSE
	lcAlias=UPPER(tcAlias)
ENDIF
IF EMPTY(tcSystemAlias)
	tcSystemAlias= "SYSTEM" 
ENDIF

lcID=''
lcOldReprocess=SET('REPROCESS')
SET REPROCESS TO AUTOMATIC

IF !USED(tcSystemAlias)
	USE system.dbf IN  0  AGAIN ALIAS (tcSystemAlias)
ENDIF

SELECT (tcSystemAlias)
SET ORDER TO TagName

IF SEEK(lcAlias,tcSystemAlias,'tagname')
	IF RLOCK()
		DO CASE 
		CASE &tcSystemAlias..type= "HEX" 
			lcID=ALLTRIM(&tcSystemAlias..value)
			REPLACE &tcSystemAlias..value WITH GenerateKey(ALLTRIM(&tcSystemAlias..value)) && процедура генерации ключа
		CASE &tcSystemAlias..type= "DEC" 
			lcID=INT(VAL(&tcSystemAlias..value))
			REPLACE &tcSystemAlias..value WITH PADL(lcID+ 1 ,FSIZE( "value" ), "0 ")
		CASE &tcSystemAlias..type= "STR" 
			lcID=ALLTRIM(&tcSystemAlias..value)
			lnID=INT(VAL(&tcSystemAlias..value))
			REPLACE &tcSystemAlias..value WITH PADL(lnID+ 1 ,LEN(lcID), "0 ")
		OTHERWISE	&& аналог  "HEX" 
			lcID=ALLTRIM(&tcSystemAlias..value)
			REPLACE &tcSystemAlias..value WITH GenerateKey(ALLTRIM(&tcSystemAlias..value)) && процедура генерации ключа
		ENDCASE
		UNLOCK
	ELSE
		=Islocked()
		=Alert( "Не могу заблокировать таблицу генерации ключей!" +;
		       " Генерация нового ключа сейчас невозможна" )
	ENDIF
ELSE
	INSERT INTO (tcSystemAlias) (tagname, value, type) ;
		VALUES (lcAlias, PADL( "0 ",FSIZE( "value" ), "0 "),  "HEX" )
	lcID=ALLTRIM(&tcSystemAlias..value)
	REPLACE &tcSystemAlias..value WITH GenerateKey(ALLTRIM(&tcSystemAlias..value)) && процедура генерации ключа
	=Alert( "Таблица " +lcAlias+ " не найдена в БД генерации ключей. " + ;
		 "Новая запись была создана автоматически. Сообщите разработчикам!" )
ENDIF

FLUSH

SELECT (lnOldArea)
SET REPROCESS TO lcOldReprocess
RETURN lcID


***************************************************************************
*	Непосредственная генерация  36 -ричного значения
***************************************************************************
FUNCTION GenerateKey
PARAMETERS tcValue
#DEFINE	NINE		 57 			&& ASC('9')
#DEFINE	CAP_Z		 90 			&& ASC('Z')
#DEFINE	LOW_Z		 122 			&& ASC('z')
#DEFINE	KEY_SPACE	 32 			&& ASC(' ')

PRIVATE lnDigit, lnStringLenght, lnChar, lcCar, lcID, lcValue

lcValue=tcValue
lcID=''

* Цикл обратного просмотра ключа для увеличения его на  1 
lnStringLength=LEN(lcValue)
FOR lnDigit=lnStringLength TO  1  STEP - 1 
	lnChar=ASC(SUBSTR(lcValue,lnDigit, 1 ))
	IF lnChar=CAP_Z		&&  36 -ричная система
		lcValue=LEFT(lcValue,lnDigit- 1 )+ ;
			'0'+RIGHT(lcValue,lnStringLength-lnDigit)
	ELSE
		DO CASE
			CASE lnChar=NINE
				lcChar='A'
			CASE lnChar=CAP_Z
				lcChar='a'
			CASE lnChar=KEY_SPACE
				lcChar='1'
			OTHERWISE
				lcChar=CHR(lnChar+ 1 )
		ENDCASE
		lcID=LEFT(lcValue,lnDigit- 1 )+ ;
			lcChar+ ;
			RIGHT(lcValue,lnStringLength-lnDigit)
		EXIT
	ENDIF
ENDFOR

IF EMPTY(lcID)
	lcID=REPLICATE('0',lnStringLength- 1 )+'1'
ENDIF
RETURN lcID
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32441444
Sergey Ch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного не в тему, но если нужен уникальный суррогатный ключ, то я пользуюсь функцией sys(2015) - MS гарантирует, что все значения будут уникальными... Пока так оно и было. Эту функцию можно вставлять в Insert...
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32441456
Фотография Hel!Riser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Sergey Ch
в сети она может не катить ;) А помница еще в FPD на _одной_ машине лабала _одинаковые_ названия. Когад пентюшки быстренькие пошли
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32441490
Sergey Ch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все может быть :)

Ставил аналогичный эксперемент в сети - 1 Gb/s - машины были в основном Xenon 2.4 Ghz, в таблице с 1000000 записей - все значения шли почти по порядку. Двойных не было, а может мне просто повезло...
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32441508
Muric
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А если еще к этому использовать имя пользователя в сети?
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32441533
Crip
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лучше сгенирить GUID
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
MESSAGEBOX(guidtoidx(newguid()))
function NewGuid() as String @ 
    
   local cGuid as String  
   declare Integer CoCreateGuid in ole32.dll String @ 
    
   cGuid = Space( 16 ) 
   CoCreateGuid(@cGuid) 
   DO WHILE ASC(LEFT(cGuid, 1 ))= 0  
        CoCreateGuid(@cGuid) 
   ENDDO 
   return cGuid 
 endfunc 
  
 * GuidToIdx 
  
 function GuidToIdx(cGuid as String) as String 
  
   local cGuidString as String  
  
   declare Integer StringFromGUID2 in ole32.dll String, String @, Integer     
  
   cGuidString = Space( 38 * 2 ) 
   StringFromGuid2(cGuid, @cGuidString, Len(cGuidString)) 
   return StrConv(cGuidString,  6 ) 
 endfunc 
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32441652
Фотография oz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Hel!Riser
sys(2015), равно как и sys(3) уникально в течение одной милисекунды. используй например str(recno()) + sys(2015) и будет тебе ШАСТЬЕ (компы, на которых фокс сможет вставить, удалить а потом снова вставить запись в течение одной милисекунды появястя оооччччень не скоро:-))

------------------------------------------------
Who is Fuck the Alise?
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32444351
Фотография MaestroEv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно еще на всякий случай перед вставкой "уникального" значения поискать его в таблице и если !seek - смело вставлять!
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32444825
MegaSuperLamer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
to Crip
Для чайников - можно пару фраз коментариев к приведённому коду.
Заранее спасибо!!!!!!!!!!!!!!!!!!!!!!
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32446926
LLamer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Уважаемые участники форума!
ДЛЯ ЧАЙНИКОВ!
Кто использует приведённый Crip'ом код.
Пожалуйста, несколько фраз комментариев. Вообще, оптимальное ли это решение. Позарез нужен уникальный индекс.(VFP 7).
БОЛЬШОЕ СПАСИБО ВСЕМ, КТО ОТКЛИКНЕТСЯ!
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32446977
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Специально для "чайников"

Сделайте поиск в данном форме по ключевому слову "NewID"

Код, предложенный Crip предполагает генерацию уникального ключа в пределах ВСЕЙ базы данных. Т.е. даже в разных таблицах значение ключа не должно повторятся. Вам действительно нужны такие строгости?
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447031
LLamer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ, топик называется <Вставка в таблицу записи с уникальным id>
Там приведён Ваш код генерации уникального ключа. Буду разбираться.
Или я смотрю не там?
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447082
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поясления к коду Crip.

The CoCreateGuid function calls the RPC function UuidCreate , which creates a GUID, a globally unique 128-bit integer. Use the CoCreateGuid function when you need an absolutely unique number that you will use as a persistent identifier in a distributed environment.To a very high degree of certainty, this function returns a unique value – no other invocation, on the same or any other system (networked or not), should return the same value .

Microsoft обозвала термином GUID (Global Unique IDentifier) идентификатор UUID (Universal Unique IDentifier), в инете полно определений, что это такое, например, здесь - "What is a UUID?" .

А вот нужна ли вам такая уникальность - решайте сами.
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447090
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Там. Это код генерации уникального ID в пределах одной таблицы. Т.е. значение ID из разных таблиц могут совпадать.

Код основан на сохранении последнего использованного значения ID в специальной служебной таблице. При создании новой записи это сохраненное значение увеличивается на 1 и используется как новое значение.
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447126
LLamer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ, для полных даунов...
IF CursorGetProp('buffering','TabLists')>1 AND TableUpdate(.F.,.T.,'TabLists')=.F.
* Если на служебную таблицу была установлена буферизация и сброс буфера
* не удался, то делаю откат буфера, причем результат этого отката уже
* не имеет значения
TableRevert(.F.,'TabLists')
ELSE
lnNewID=TabLists.LastID
ENDIF[quot автор][/quot]
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447143
LLamer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Прошу прощения, клацнул не туда
ВладимирМ
ВладимирМ, для полных даунов...
IF CursorGetProp('buffering','TabLists')>1 AND TableUpdate(.F.,.T.,'TabLists')=.F.
* Если на служебную таблицу была установлена буферизация и сброс буфера
* не удался, то делаю откат буфера, причем результат этого отката уже
* не имеет значения
TableRevert(.F.,'TabLists')
ELSE
lnNewID=TabLists.LastID
ENDIF
При каких условиях сброс буфера может не удасться и мои действия и почему результат отката уже не имеет значения??????
Тысяча извинений за назойливость!!!!!
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447159
guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте
>Здесь используется служебная таблица TabLists из базы данных Leasing >следующей структуры
Подскажите, пожалуйста, в чём ньюанс использования именно базы. а не свободной таблицы?
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447215
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При использовании свободных таблиц невозможна транзакция. А при открытой транзакции есть ряд ограничений, которые надо учитывать в коде.

Кроме того, предполагается, что вызов функции обычно будет производится из Default ключевого поля таблицы. А это также невозможно в свободных таблицах.

В принципе, приведенный код подойдет и для свободных таблицы.

Подробнее о базе данных почитай здесь

http://www.foxclub.ru/kb/index.php?sid=28924&aktion=artikel&rubrik=004&id=5&lang=ru#DataBase
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447237
badhead
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимирМ!
Всё понятно, за ислючением следующего:
1. При каких условиях сброс буфера может не удасться и как обрабатывать эту ситуацию
2. Почему результат отката уже не имеет значения.
Спасибо, если найдёте время ответить.
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447257
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Ну, в данном случае я предполагал, что другим пользователем открыта транзакция и он первым успел создать новую запись. В этом случае до закрытия транзакции запись служебной таблицы будет заблокирована и никто ничего не сможет в нее записать. TableUpdate() будет возвращать .F.

2. Если сброс буфера не произошел, то это ошибка генерации нового значения. Значит эту ситуацию следует как-то обработать в вызвавшей программе. Скорее всего, там или будет предпринята попытка повторной генерации ключа или глобальный откат вообще всех изменений

Кроме того, ситауция когда не получился откат буфера я себе как-то не представляю. Т.е. наверно это возможно (раз такое предусматривается самой командой), но я пока не встречал.
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447276
badhead
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Большое спасибо, ВладимирМ !
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447325
Urri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Отвечу за ВладимираМ

Основная причина того, что сброс буфера может не удасться - конфликт при блокировке (другая транзакция заблокировала запись и никак не завершится). Могут быть и другие причины, но разбирать их не так интересно, как определить способ обработки ошибок.

Если увеличить счетчик в таблице поддержки идентификаторов не получилось, то проводить сохранение далее нельзя. Функция NewID может вернуть .Null. - при условии, что используется контейнер БД, а ID объявлен первичным ключом (или, если значение счетчика вставляется в неключевое поле, можно на это поле назначить условие is not .null.), этого будет достаточно, чтобы вызвать ошибку вставки в таблицу. Но эту ошибку, в свою очередь, нужно корректно обработать в клиентском приложении. Обычно решение предоставляется пользователю (например, мы откатываем текущую транзакцию и говорим пользователю в messagebox'е, что вставка не получилась, не хотите ли попробовать еще раз (Да/Нет) - по "Да" повторяем попытку).

В случае, если выполняется автоматическая обработка, messagebox не пойдет - он же ее остановит, не так ли? Можно попытаться, например, сохранить данные автоматом еще пару раз, и если-таки вставка не прошла, сбросить сообщение об ошибке в log, сохранить куда-то отвергнутые данные и продолжить работу. Или пытаться сохранить снова и снова, до тех пор, пока не получится ;-)

Ну и общий совет - всегда использовать короткие по времени транзакции и оптимистические блокировки. Правда, в этом случае нужно будет обрабатывать значительно больше исключений, зато в сети всем будет хорошо.
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447368
Фотография FM32YO aka KID
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
по поводу ""испоьзовать КОРОТКИЕ по времени транзакции.. что-то я е понимаю...
Транзакция допустим вешается на кнопку "Сохранить данные", под которой кликметод - несколько

begin transaction
UPDATE or INSERT
UPDATE or INSERT
.
.
.
UPDATE or INSERT
END TRANSACTION

так? время транзакции = времени произведенных изменений.....
или же кто-то делает начало транзакции при открытии форму, а конец ее после зактытия, и, если оператор открыв форму пошел покурить - транзакция остается открытой - это "длинная по времени транзакция" ???
Я правильно понял???
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447406
Urri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, я как раз предостерегал против начала транзакции с открытием формы и конца - с закрытием ;-)
Вам это может показаться смешным, но я, например, знаю людей, которые начинающие и порываются сделать именно так ;-)
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447481
Фотография FM32YO aka KID
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а вот оно что.. а то я думаю КАК это "человек заболел а транзакцию не закрыл"
я-то и подумать не мог, что кто-то ТАК реализует механизм транзакций...
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32447902
badhead
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного не в тему Тире может кто снизойдёт до ответа Зпт
как отладчиком пройтись по хранимой процедуре Тире точки прерывания ставятся Зпт а в окно отладчика не вываливается Тчк
СПАСИБО ВоскзнакВоскзнакВоскзнакВоскзнакВоскзнак
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32448504
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Badhead

О какой версии FoxPro речь и как ты ставишь точки прерывания?

Пробовал ставить точки прерывания на команде, которая вызывает срабатывание хранимой процедуры (т.е. не в самой хранимой процедуре)?

А явно прописать точку останова командой:

SET STEP ON

не пробовал?
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32448819
badhead
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимируМ
Спасибо, всё заработало, единственное, появился вопрос, а как поставить точку прерывания на сам вызов ХП -
>Пробовал ставить точки прерывания на команде, которая вызывает >срабатывание хранимой процедуры
У меня стоит вызов по Default занесения уник. значения с исползованием Вашего кода.(VFP7)
...
Рейтинг: 0 / 0
Уникальный индекс номера записи
    #32449080
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Default срабатывает если в момент создания новой записи явно не указано значение поля на котором стоит Default

Т.е. Default сработает на командах вида
APPEND BLANK
INSERT INTO ... - если в списке не указано поле с Default

А вот в случаях явного указания значения поля, например, через INSERT INTO (т.е. есть в списке полей) Default не сработает.
...
Рейтинг: 0 / 0
30 сообщений из 30, показаны все 2 страниц
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Уникальный индекс номера записи
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]