首先让我说我根本无法修改数据库模式。
我无权访问与数据库交互的任何现有代码。它是一个已编译的程序集,我无法反编译。
我有一个数据库表,其值在代码中逻辑上用作主键,但不会自动递增。
现在这里是转折点,有时键增加正数,有时增加负数。:(
找不到任何hilo代码的证据。
除了执行 SELECT TOP 1 之外,我不知道如何处理这个问题,添加一个值并希望不会发生重叠。
首先让我说我根本无法修改数据库模式。
我无权访问与数据库交互的任何现有代码。它是一个已编译的程序集,我无法反编译。
我有一个数据库表,其值在代码中逻辑上用作主键,但不会自动递增。
现在这里是转折点,有时键增加正数,有时增加负数。:(
找不到任何hilo代码的证据。
除了执行 SELECT TOP 1 之外,我不知道如何处理这个问题,添加一个值并希望不会发生重叠。
如果您的表是数据库容器 (*.DBC) 的一部分而不是空闲表,那么您可能会找到自动递增数据库容器中的键的代码。
如果您打开表并使用 MODIFY STRUCTURE 命令,您可以在第三个选项卡上看到表的属性。如果表是数据库容器的成员,则将显示数据库的名称以及任何规则,包括触发器和记录规则,这些规则在每次写入表时执行。
在添加自动递增字段之前的日子里,我通过添加如下记录规则来实现自动递增字段:
PROCEDURE TABLE_RR
LOCAL nOldArea,nUnique
IF PK=0 &&Only update primary key field when not already set
STORE SELECT() TO nOldArea
&&Open table again in another work area, we can't move the record pointer in a Rule
IF !USED("TABLE_RR")
USE TABLE.DBF IN 0 NOUPDATE AGAIN ALIAS TABLE_RR
ENDIF
&&Find current maximum value of primary key field, add 1 as next primary key field
SELECT TABLE_RR
SET ORDER TO PKTable
GO BOTT
STORE 1+PK TO nUnique
&&Update primary key field for our record
SELECT(nOldArea)
REPLACE PK WITH nUnique
ENDIF
&&Record rule must return true or changes are rejected
RETURN .T.
ENDPROC
将此类规则存储在数据库容器存储过程代码区是正常的习惯和做法,但是,只要正在运行的应用程序能够找到该函数,它就会执行。显然,上面的代码示例假定表名为 TABLE,有一个名为 PK 的数字(最好是 Int)字段,索引标记为 PKTable。
因为代码在记录规则中,所以它在任何更新期间都会在记录上执行,因此在记录被锁定时,不会发生冲突。PK 中没有值的任何记录都会得到 1 + 该字段的当前最高值。记录规则旨在验证记录并拒绝无效值,并且必须返回 true (.T.) 才能接受写入。过程中可能会出现其他代码,包括将当前值设置为时间戳字段等。
记录规则可以通过 ALTER TABLE 命令应用于表:
ALTER TABLE 'TABLENAME' SET CHECK PROCEDURENAME()
或通过 MODIFY STRUCTURE 的交互式表格编辑器
尽管史蒂夫的解决方案非常好,尤其是利用数据库容器和分配规则,但您显然(有点)陷入困境。如果您尝试添加记录并需要创建自己的自动增量,您可能必须通过过程调用并分配它来完成。这只是一个示例,但可能会对您有所帮助。
FUNCTION AddMyNewRecord()
*/ localized variable so you don't accidentally mangle some otherwise
*/ coincidental variable somewhere else. Preserve work area at start
local lnSelect, llSaveOk, lnAttempts, lnNewPKID
lnSelect = select()
llSaveOk = .f.
select YourAddressTable
if NOT FLOCK()
lnAttempts = 0
do while lnAttempts < 10 AND NOT FLOCK()
wait window "Attempting lock for address table..." timeout 1
enddo
endif
if NOT FLOCK()
messagebox( "Unable to lock file to add next record primary key." )
else
*/ We have a lock, now try to detect both the highest and lowest
*/ EXISTING key for the table
use in select( "C_TryNextKey" )
select MIN( YAT.PK ) as MinKey,;
MAX( YAT.PK ) as MaxKey ;
from ;
YourAddressTable YAT;
into ;
cursor C_TryNextKey readwrite
*/ Determine if you need higher or lower key sequence
if CriteriaForPositiveKey
lnNewPKID = C_TryNextKey.MaxKey +1
else
*/ must be getting next LOWER sequence
lnNewPKID = C_TryNextKey.MinKey -1
endif
*/ close temp cursor from getting respective high / low key
use in select( "C_TryNextKey" )
*/ NOW, we can add the new record
Select YourAddressTable
APPEND BLANK
*/ replace PK and all the other fields you need to do too
Replace PK with lnNewPKID,;
Address1 with lcSomeVariableYouHaveForAddress1,;
Address2 with lcSomeVariableForAddress2,;
AnyOtherFields with lcOtherFieldsToBeSet
*/ Unlock the address table
UNLOCK
*/ set flag so we know it worked vs not.
llSaveOk = .t.
endif
*/ Return back where it started
select( lnSelect )
*/ Return if the save was ok or not.
return llSaveOk
endproc
这不会修改现有的数据库,也不会修改表结构。但是,它会在插入新记录内容之前尝试锁定表。然后查看最低和最高 ID。您将不得不分析数据以找出为什么有些人有负面与正面,并更新我在上面代码中的“占位符”放置的条件。最后,解锁桌子。
如果这是有道理的,那就太好了,如果您需要调整,请告诉我,我会尽力为您提供更多指导。
不知道你需要什么,但是如果你需要额外的PK,你可以使用记录号:
SELECT RECNO() FROM table1