注册 登录
编程论坛 VFP论坛

【求助】ssek结果出错

zhousr 发布于 2024-05-17 12:56, 212 次点击
从一个总表中按不同条件筛选出部分结果,通过seek找出最匹配的行号。如果在这条记录后面的记录数超过90条,则把多出的记录删除。在绝大部分情况下,seek出的行号是正确的。但偶尔出现seek出的行号为0,不能得出正确结果。附件中分别给出了2个测试用表及部分代码,请指教!
另外,通过检查发现,seek出的行号,大部分情况是与条件最匹配的,少数情况下会指向最匹配行的下一行。不知是何原因?

只有本站会员才能查看附件,请 登录
8 回复
#2
zhousr2024-05-17 13:24
代码如下:

*** a表的Z正确,a1表的Z错误。

USE a1
SORT TO sxb ON zhbfd
use
USE sxb IN 0
SELECT sxb

*wcbfd=VAL(STRCONV(wch,2))/300000*100  &&程序中从另一个表单取wch,此处测试时简化,直接赋值
*wcbfd=8.85  && a表测试用
wcbfd=34.958  && a1 表测试用
 r=RECCOUNT()  &&表总行数

 SET NEAR ON
 INDEX on zhbfd TAG wc
 SEEK wcbfd
z=RECNO(0)
?z  &&显示Z=0
GO z
SCATTER TO aLs
REPLACE bzk WITH "囙"  &&奇怪的是,虽然显示Z=0,但这一步却能找到正确的Z行,并成功替换

IF r-z>91
GO z+91  &&虽然上面一行执行时使用了正确的Z,但这里的Z却为0,把91行后的全删除了。
DELETE REST
ENDIF
#3
sdta2024-05-17 13:56
SET NEAR 命令
请参阅
 全部折叠 全部展开
确定 FIND 或 SEEK 查找记录不成功时记录指针的位置。

 
SET NEAR ON | OFF
 

参数
ON

如果使用 FIND 或 SEEK 搜索记录不成功,则将记录指针定位在最相近的记录上。使用此设置时,RECNO( ) 返回最相近的记录的记录编号,FOUND( ) 返回假(.F.),EOF( ) 返回假(.F.)。
OFF

(默认) 如果使用 FIND 或 SEEK 搜索记录不成功,则将记录指针定位在表尾。使用此设置时,RECNO( ) 返回表中记录加 1 的数值,FOUND( ) 返回假(.F.),EOF( ) 返回真(.T.)。
说明
当没有记录符合搜索标准时,搜索不成功。

如果搜索不成功,则无论 SET NEAR 的设置如何,发出带有参数 0 的 RECNO( ) 都会返回最相近记录的记录编号。

SET NEAR 的作用域是当前数据工作期。
#4
zhousr2024-05-17 14:20
非常感谢!!
一直用RECN(0),是因为这是你在论坛里告诉我的,没碰到问题就一直没想到会有问题

另外,通过检查发现,seek出的行号,大部分情况是与条件最匹配的,少数情况下会指向最匹配行的下一行。这个不知有何指教?

#5
sdta2024-05-17 15:26
以下是引用zhousr在2024-5-17 14:20:35的发言:

非常感谢!!
一直用RECN(0),是因为这是你在论坛里告诉我的,没碰到问题就一直没想到会有问题

另外,通过检查发现,seek出的行号,大部分情况是与条件最匹配的,少数情况下会指向最匹配行的下一行。这个不知有何指教?

认真看看帮助文件中
SET NEAR 命令的用法
#6
schtg2024-05-18 07:06
回复 2楼 zhousr
只有本站会员才能查看附件,请 登录
#7
liuxingang282024-05-20 15:03
看了一下楼主的代码,下面谈谈我对此问题的理解:

1. 在设置了 set near on 时,根本不需要引用 recn(0),直接引用 recn()即可。我的理解是:recn(0)只有在 set near off 时才有意义
2. 即使 seek 命令搜索成功,即:found()=.t.,也有可能 recn()≠recn(0)。在帮助文件中也说了,“在 SEEK 命令搜索失败时,recn(0)返回最匹配记录的记录号”,但并未说搜索成功时,recn(0)也返回最匹配记录的记录号。
3. 由于 recn(0)可能返回 0,而 go 0 是错误的,因此,在执行 go 语句前必须判断记录跳转值

下面是我改进后的示例:

示例一:
SELECT sxb
wcbfd = 34.958
r = RECCOUNT()  &&表总行数
SET NEAR ON
INDEX on zhbfd TAG wc
SEEK wcbfd
z = RECNO()
? z
if !found()
    ? '未找到匹配记录!'
    retu
endif
GO z
SCATTER TO aLs
REPLACE bzk WITH "囙"
IF r-z > 91
    GO z+91
    DELETE REST
ENDIF

示例二:
SELECT sxb
wcbfd = 34.958
r = RECCOUNT()  &&表总行数
SET NEAR OFF
INDEX on zhbfd TAG wc
SEEK wcbfd
if found()
    z = RECNO()
else
    z = recno(0)
    if z = 0
        ? '未找到匹配记录!'
        retu
     endif
endif
?z
GO z
SCATTER TO aLs
REPLACE bzk WITH "囙"
IF r-z > 91
    GO z+91
    DELETE REST
ENDIF

[此贴子已经被作者于2024-5-20 15:04编辑过]

#8
zhousr2024-05-22 09:58
liuxingang28,非常感谢!!
schtg,我EDGE年不见图片,按论坛里说的也没搞定
#9
zhousr2024-05-23 08:38
人老了,不中用了
seek的说明,就把第二个问题的答案摆在那里:

说明

只能在索引过的表中使用 seek 命令,并且只能搜索索引关键字。除非 SET EXACT 的设置为 OFF ,否则匹配指的是完全匹配。
如果 SEEK 找到了与索引关键字相匹配的记录,则 RECNO( ) 返回匹配记录的记录号;FOUND( ) 返回“真”(.T.);EOF( ) 返回“假”(.F.)。
如果找不到相匹配的关键字,则 RECNO( ) 将表中记录的个数加 1,然后返回;FOUND( ) 返回“假”(.F.);EOF( ) 返回“真”(.T.)。
如果 SET NEAR 设置为 ON ,则记录指针指向与索引关键字最相匹配的那个记录的后面一个记录。如果 SET NEAR 设置为 OFF,则记录指针指向文件的结尾。在这两种情况下,RECNO(0) 都返回与关键字最匹配的记录号。
1