關係運算子

在所有運算子中,關係運算子是最複雜的運算子,這就是我們將它們留到最後的原因。

關係運算子也稱為比較運算子,它們用於比較事物。

比較結果是布林值 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 設定的影響。