Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Уникальный индекс номера записи / 25 сообщений из 30, страница 1 из 2
15.03.2004, 09:27
    #32441343
Muric
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Уникальный индекс номера записи
Доброе утро!
Ситуация такая:
В одном методе у меня согласно признаку (редактирования или добавления записи) происходят эти действия. Сначала у меня при добавлении новой записи была инструкция INSERT только для тех полей, где проверяется целостность базы данных, а зетем шел REPLACE. Когда попробовал это действие по сети, то у меня возникли существенные задержки при добавлении новой записи. Я убрал REPLACE и в инструкцию INSERT поместил изменения всех значений полей. Результат был потрясающим. Но проблема была в том, что помимо INSERT необходимо делать и просто обнавление данных. В обновлении данных у меня по-прежнему участвует REPLACE. Может быть использовать UPDATE? Тогда необходимо иcпользовать уникальный индекс номера записи. Есть ли в VFP6 возможность автоматического добавления уникального номера записи или необходимо самому создать такое поле? Если самому создавать такое поле, то как присваивать номер для записи, т.е. по RECNO() записи или как-то по-другому?
Буду благодарен за советы!
...
Рейтинг: 0 / 0
15.03.2004, 10:33
    #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
15.03.2004, 10:45
    #32441444
Sergey Ch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Уникальный индекс номера записи
Немного не в тему, но если нужен уникальный суррогатный ключ, то я пользуюсь функцией sys(2015) - MS гарантирует, что все значения будут уникальными... Пока так оно и было. Эту функцию можно вставлять в Insert...
...
Рейтинг: 0 / 0
15.03.2004, 10:55
    #32441456
Hel!Riser
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Уникальный индекс номера записи
2 Sergey Ch
в сети она может не катить ;) А помница еще в FPD на _одной_ машине лабала _одинаковые_ названия. Когад пентюшки быстренькие пошли
...
Рейтинг: 0 / 0
15.03.2004, 11:11
    #32441490
Sergey Ch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Уникальный индекс номера записи
Все может быть :)

Ставил аналогичный эксперемент в сети - 1 Gb/s - машины были в основном Xenon 2.4 Ghz, в таблице с 1000000 записей - все значения шли почти по порядку. Двойных не было, а может мне просто повезло...
...
Рейтинг: 0 / 0
15.03.2004, 11:16
    #32441508
Muric
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Уникальный индекс номера записи
А если еще к этому использовать имя пользователя в сети?
...
Рейтинг: 0 / 0
15.03.2004, 11:25
    #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
15.03.2004, 12:16
    #32441652
oz
oz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Уникальный индекс номера записи
2 Hel!Riser
sys(2015), равно как и sys(3) уникально в течение одной милисекунды. используй например str(recno()) + sys(2015) и будет тебе ШАСТЬЕ (компы, на которых фокс сможет вставить, удалить а потом снова вставить запись в течение одной милисекунды появястя оооччччень не скоро:-))

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

так? время транзакции = времени произведенных изменений.....
или же кто-то делает начало транзакции при открытии форму, а конец ее после зактытия, и, если оператор открыв форму пошел покурить - транзакция остается открытой - это "длинная по времени транзакция" ???
Я правильно понял???
...
Рейтинг: 0 / 0
18.03.2004, 14:48
    #32447406
Urri
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Уникальный индекс номера записи
Да, я как раз предостерегал против начала транзакции с открытием формы и конца - с закрытием ;-)
Вам это может показаться смешным, но я, например, знаю людей, которые начинающие и порываются сделать именно так ;-)
...
Рейтинг: 0 / 0
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Уникальный индекс номера записи / 25 сообщений из 30, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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