关系运算符

在所有运算符中,关系运算符是最复杂的运算符,这就是我们将它们留到最后的原因。

关系运算符也称为比较运算符,它们用于比较事物。

比较结果是布尔值 false 或 true。

有趣的是,如果你在 VFP 帮助中检查它,你只能看到一个简短的列表操作和更多的行,就好像它是关于那些运算符的。

嗯,复杂性来自这样一个事实:它们可以在任何类型上运行,无论是数字,日期,日期时间,逻辑还是字符串,甚至是对象。此外,行为可能看起来很尴尬,除非你知道结果会产生什么影响,否则你得不到你的期望。

让我们从关系运算符列表开始:

操作者 描述 MOST 基本样本
> 比…更棒 ?1> 2 && .F。
< 少于 ?1 <2 && .T。
> = 大于或等于 ?1> = 2 &&。F。
<= 小于或等于 ?1 <= 2 && .T。
\= 等于 ?1 = 1 && .T。
\== 完全等于(对字符串有意义) ? ‘1’=‘1’&& .T。
!=,#,<> 不等于(所有 3 个运算符的行为方式相同,选择你最喜欢的) ?1 != 1 && .F。

尽管可以将这些用于所有数据类型,但操作数之间应该存在类型兼容性。例如,如果你尝试将 Date 与 Integer 进行比较,则会出现错误。

可以比较日期和日期时间,尽管它们是不同的类型,VFP 会隐式为你进行转换。

? Date() > DateTime() && .F. 
? Date() <= DateTime() && .T. 
? Date() < DateTime() && .T. if it is not midnight

当操作数是数字时,所有这些操作符都很简单直接,它们就像在数学表达式中那样工作。

有了逻辑操作数,F。被认为小于 .T。

对象我们比较的是对象在内存中的引用。因此,最常用的比较是确定两个对象变量是否指向同一个对象。即:

local o1, o2
o1 = createobject('Label')
o2 = createobject('Label')
? m.o1 = m.o2 && is o1 and o2 the same object?
? m.o1 > m.o2 && this would work too but likely you would never use

* remember we are comparing their references in memory
* 
* They are different objects, but do they have any difference in their properties?
? CompObj(m.o1, m.o2) && .T. They are identical properties wise

字符数据类型的比较,即字符串的比较是 VFP 中最令人困惑的。它不像其他语言和/或数据库那样工作,并且对 VFP 是独一无二的(也可能是其他一些 xBase 语言)。

许多年前,我甚至看到社区中一些非常先进的成员,他们还不知道这些运算符如何在 VFP 中运作。因此,可以理解的是,轻微的细微差别可能会让新手容易混淆。

比较基本上是关于相等与否。如果它们不相等,那么我们可能会考虑运算符>,<,> =,<=,对吗?对于字符串,当两个字符串被认为相等时,它会令人困惑。

重要提示: VFP 字符串区分大小写。 ‘A’和’a’是两个不同的字符串。对于许多数据库而言,情况并非如此,其中默认情况下使用不区分大小写的排序规则。例如,在使用不区分大小写(CI)排序规则创建的表上的 postgreSQL 或 MS SQL Server 中:

select * from myTable where Country = 'TURKEY'

select * from myTable where Country = 'Turkey'

会产生相同的结果。在 VFP 中虽然只能获得套管匹配的那些。然而,VFP 具有一些整理支持并且使得不区分大小写的比较。 (不要相信,见下文)

  • 如果两个字符串不相等,那么这么好,只要你没有更改任何默认值,那么它们将*根据它们的 ASCII 值*进行比较。

    ? 'Basoz' < 'Cetin' && is true.
    ? 'basoz' < 'Cetin' && is false.
    ? 'Cetin' < 'David' && is true.
    ? 'Çetin' < 'David' && is false.
    

整理的默认值是机器,这就是你得到的。当你将排序规则更改为其他内容时,你将根据该排序规则的排序顺序进行比较。对于默认计算机以外的排序规则设置,你还意味着比较不区分大小写(不要相信这是相同的):

  set collate to 'GENERAL'
  ? 'Basoz' < 'Cetin'
  ? 'basoz' < 'Cetin'
  ? 'Cetin' < 'David'
  ? 'Çetin' < 'David'

现在所有这些表达式都是正确的。

个人建议:VFP 中的排序规则从来都不够可靠。我建议你不要使用排序规则并坚持使用默认的’MACHINE’。如果你要使用排序规则,那么请记住,当你遇到关于字符数据的非常意外的事情时,请先检查它。我已经看到并证明它在许多情况下都失败了,但后来我在 VFP9 版本之前停止尝试使用它,它现在可能是一致的,我真的不知道。

考虑到我们用字符串覆盖不等式情况,棘手的是同等情况。在 VFP 中基本上有两个设置影响比较:

  1. SET EXACT(默认为 OFF 并影响常规比较 - 除了 SQL 之外)
  2. SET ANSI(默认为 OFF 并仅在 SQL 中进行效果比较 .SET EXACT 对 SQL 查询中的比较没有影响

使用 SET EXACT OFF,读取比较为右边的字符串是否为左边的字符串?它们与正确的字符串长度进行比较。

? "Bobby" = "B" && Bobby starts with B, so TRUE
? "Bobby" = "Bob" && Bobby starts with Bob, so TRUE
? "Bobby" = "Bob " && Bobby starts with Bob but there is a trailing space there, FALSE
? "Bobby" = "bob" && would be true with collation set to GENERAL

注意,通过常规比较,Bobby=B 为 TRUE,但 B=Bobby 为 FALSE。换句话说,操作数的位置很重要。

使用 SET EXACT ON 时,字符串必须完全匹配,但忽略它们的尾随空格(我们忽略了 set collat​​e,这也会使用大小写不敏感):

? "BOBBY" = "BOB" && FALSE 
? "BOBBY" = "BOBBY" && TRUE
? "BOBBY" = "BOBBY     " && TRUE 
? "BOBBY     " = "BOBBY" && TRUE

现在,使用 SQL 命令 SET EXACT 没有任何效果,它的行为就像 SET EXACT OFF 一样。

Select * from Customers where Country = 'U'

从美国,英国选择以’U’开头的任何国家的客户。

但是,在 SQL 中,根据定义,更改操作数的顺序应该会产生相同的结果。从而:

Select * from Customers where 'U' = Country

也会以相同的方式工作(请注意与非 SQL 命令的区别)。

当你想暗示完全匹配时,一个选项是打开 ANSI:

SET ANSI ON
Select * from Customers where Country = 'USA'

返回来自美国的所有客户。请注意,将忽略国家/地区字段 OR 中右侧表达式的尾随空格。无论你有多少落后都没关系。你可以像进行比较一样进行比较:RTRIM(Country)= RTRIM(’USA’)。

尽管在 VFP 中的操作符中未提及,但 SQL 运算符是 LIKE。当你使用 LIKE 时,无论 SET ANSI 设置如何,你都会获得完全匹配的比较(使用 LIKE 强制和隐式 ANSI ON 情况 - 毕竟它是 ANSI 运算符)。但是,请注意行为略有不同。除非带有预告片的总大小等于或小于字段大小,否则它不会忽略尾随空格。例如,如果 Country 字段是 C(10),则 Country =‘USA’或 Country =‘USA__‘将起作用,但 Country =‘USA___________‘将失败( 下划线表示一个空格,最后一个表示多于 7 个尾随空格)。

最后我们是最后一个运算符,==。这意味着完全相同,并使用字符串。一个优点是,使用==你总是意味着你想要完全匹配,无论 SET EXACT 或 SET ANSI 设置如何。但是请注意,当它是 SQL 命令或非 SQL 常规命令时,它的行为是不同的。

使用 SQL:

Select * from Customers where Country == 'USA'

无论 ANSI 和 EXACT 设置如何,我们都希望所有来自美国的客户。任何一侧的尾随空格都会被忽略。

使用非 SQL:

? m.lcString1 == m.lcString2

只有在它们的套管和长度完全相同时才会成立 (尾随空格不会被忽略)。它不受 SET ANSI,EXACT 或 COLLATE 设置的影响。