Предупреждение: ваш код испорчен в многопользовательской среде. Два человека могут одновременно запускать запрос и получать одинаковый идентификатор. Один из них потерпит неудачу в INSERT, если в столбце есть первичный или кандидатный ключ, что является лучшей практикой для ключевых полей.
Моя рекомендация состоит в том, чтобы иметь идентификатор, являющийся автоматически увеличивающимся целым полем (я не являюсь их фанатом), или даже лучше создать таблицу ключей. Каждая запись в таблице предназначена для таблицы, которая получает назначенные ключи. Я использую структуру, аналогичную этой:
Structure for: countergenerator.dbf
Database Name: conferencereg.dbc
Long table name: countergenerator
Number of records: 0
Last updated: 11/08/2008
Memo file block size: 64
Code Page: 1252
Table Type: Visual FoxPro Table
Field Name Type Size Nulls Next Step Default
----------------------------------------------------------------------------------------------------------------
1 ccountergenerator_pk Character 36 N guid(36)
2 ckey Character (Binary) 50 Y
3 ivalue Integer 4 Y
4 mnote Memo 4 Y "Automatically created"
5 cuserid Character 30 Y
6 tupdated DateTime 8 Y DATETIME()
Index Tags:
1. Tag Name: PRIMARY
- Type: primary
- Key Expression: ccountergenerator_pk
- Filter: (nothing)
- Order: ascending
- Collate Sequence: machine
2. Tag Name: CKEY
- Type: regular
- Key Expression: lower(ckey)
- Filter: (nothing)
- Order: ascending
- Collate Sequence: machine
Теперь код для хранимой процедуры в DBC (или в другой программе) заключается в следующем:
ФУНКЦИЯ NextCounter (tcAlias)
LOCAL lcAlias,; lnNextValue,; lnOldReprocess;; lnOldArea
lnOldArea = SELECT()
IF ПАРАМЕТРАМИ() lcAlias = ALIAS()
IF CURSORGETPROP ("SourceType") = DB_SRCLOCALVIEW * - Попытка получить базовую таблицу lcAlias = LOWER (CURSORGETPROP ("ТАБЛИЦЫ")) lcAlias = SUBSTR (lcAlias, AT ("!", lcAlias) + 1) ENDIF ELSE lcAlias = LOWER (tcAlias) ENDIF
lnOrderNumber = 0 lnOldReprocess = SET ('Обработать')
* - блокировка до пользователь нажимает Esc SET Reprocess TO AUTOMATIC
если используется ("countergenerator") USE EventManagement!В countergenerator 0 ШАРЕД ALIAS countergenerator ENDIF
ВЫБОР countergenerator
ЕСЛИ SEEK (ниже (lcAlias), "countergenerator", "CKEY") ЕСЛИ RLOCK() lnNextValue = countergenerator.iValue ЗАМЕНЫ countergenerator.iValue WITH countergenerator.iValue + 1 UNLOCK ENDIF ELSE * Создайте новую запись со стартовым значением. APPEND BLANK В countergenerator SCATTER MEMVAR MEMO m.cKey = НИЖНИЙ (lcAlias) m.iValue = 1 m.mNote = "Автоматически созданный хранимая процедура." m.tUpdated = DATETIME() GATHER MEMVAR Memo
ЕСЛИ RLOCK() lnNextValue = countergenerator.iValue ЗАМЕНЫ countergenerator.iValue С countergenerator.iValue + 1 ОТПЕРЕТЬ ENDIF ENDIF
SELECT (lnOldArea) SET TO Reprocess lnOldReprocess
RETURN lnNextValue EndFunc
RLOCK() гарантирует, что для записей нет конкуренции, и он достаточно быстр, чтобы не иметь узкого места в процессе. Это намного безопаснее, чем подход, который вы сейчас используете.
Рик Schummer
VFP MVP