Rap*_*rei 0 progress-4gl openedge
我的公司有很多代码用于FIND FIRST获取第一个寄存器(在唯一字段上搜索)。
但是,在了解有关 Progress 的更多信息时,有几个地方建议我进行搜索FOR FIRST,说FIND FIRST可能找不到具有相同值的第一个寄存器。
说我需要使用唯一字段查找第一个值,这两者之间真的有区别吗?除了不需要检查该字段是否可用之外
FOR FIRST file_path WHERE file_path.file_name = "ABCDEF" NO-LOCK:
// Do my thing
END.
Run Code Online (Sandbox Code Playgroud)
FIND FIRST file_path WHERE file_path.file_name = "ABCDEF" NO-LOCK NO-ERROR.
IF AVAIL file_path THEN DO:
// Do my thing
END.
Run Code Online (Sandbox Code Playgroud)
我使用时发现的唯一问题是在没有可用记录的情况下FOR FIRST不使用。IF NOT AVAIL
您的目标记录是唯一的吗?
换句话说 - WHERE 子句是否会导致使用唯一索引?
如果是,那么您不应该使用 FIRST。在这种情况下,FIND FIRST 和 FOR FIRST 都没有帮助。两种构造都会“工作”,但它们会给维护程序员(可能是 6 个月后的您......)这样的想法:可能存在多记录结果集,并且您出于某种原因通过使用 FIRST 对它进行排序。
FIND 的设计目的是用于检索单个记录。如果您只期望一条记录,那么您不应该在每次键入 FIND 时都添加 FIRST。(是的,我知道某些知名供应商的大量代码违反了该规则。您仍然不应该这样做。)
在极少数情况下,集合存在自然且合理的排序,并且 FIRST 可能有意义。例如,日期字段有时是一个例外(在这些情况下,FIND 不是唯一的)。
您可能听说过一些关于“FIND FIRST 更快”的误解。这不是真的。唯一的 FIND 执行与 FIND FIRST 完全相同的代码路径,并且从性能角度来看它们完全没有不同。这很容易测试和验证。在任何情况下,如果 FIND FIRST “更快”,您都不会进行独特的查找,除非这是适当的罕见情况之一,否则您可能会通过使“第一”记录特殊(违反第三正常)来引入错误形式)或掩盖缺乏适当索引的情况。基本上,您可以“更快地找到错误记录”。
由于上述原因,FOR FIRST 是一个非常非常糟糕的主意,甚至更具欺骗性,因为 FOR 支持显式 BY 子句进行排序,因此,您可能认为您正在按照使用 BY 指定的排序顺序获取 FIRST 记录。
遗憾的是事实并非如此。规则是“选择,然后排序”。因此 FOR FIRST 将恰好选择一行。基于 WHERE 子句选择的不受 BY 影响的任何索引(除非在极少数情况下,两个或多个索引在索引选择规则中的适当性相关联)。然后对这一行进行排序。对一行进行排序会得到相同的一行。
您关于在使用 FOR FIRST 时无法检查 AVAILABLE 的特定问题可以被改写为一种有趣的方法。如果你不允许 FIRST 把水搅浑,那么你可以说使用 FOR 在某些方面更干净。查找数据的传统方法通常如下所示
find customer no-lock where custNum = 2 no-error.
if available customer then
display name.
else
display "oops".
Run Code Online (Sandbox Code Playgroud)
在太多情况下,代码忽略了 ELSE 的可能性。
如果您真的只想遵循快乐的道路并且不需要处理“不可用”的情况,那么:
for customer no-lock where custNum = 1:
display name.
end.
Run Code Online (Sandbox Code Playgroud)
可能是需要考虑的事情。(请注意,没有 FIRST 会让人混淆。)
至于:
...有几个地方建议我使用 FOR FIRST 进行搜索,因为 FIND FIRST 可能找不到具有相同值的第一个寄存器。
我不知道你在哪里看到这样的建议,但它要么被误解了,要么就是错误的。
所以,总而言之……如果您每次编写 FIND 时都在代码中添加 FIRST,或者根本使用 FOR FIRST,那么这是一个危险信号,表明您没有清楚地考虑该代码的实际工作原理。