查詢中可為 Null 的運算子
可為 Null 的運算子是搭配在一或兩側可為 Null 算術類型使用的二進位算術或比較運算子。 使用資料庫等允許 null 取代實際值的來源資料時,即會出現可為 Null 的型別。 可為 Null 的運算子用於查詢運算式。 除了算術和比較的可為 Null 運算子,您也可以使用轉換運算子在可為 Null 的型別間轉換。 特定查詢運算子也有可為 Null 的版本。
注意
可為 Null 的運算子通常僅用於查詢運算式。 如果您不使用查詢運算式,即不必知道或使用這些運算子。
可為 Null 運算子的資料表
下表列出 F# 中支援的可為 Null 運算子。
左側可為 Null | 右側可為 Null | 兩側可為 Null |
---|---|---|
?>= | >=? | ?>=? |
?> | >? | ?>? |
?<= | <=? | ?<=? |
?< | <? | ?<? |
?= | =? | ?=? |
?<> | <>? | ?<>? |
?+ | +? | ?+? |
?- | -? | ?-? |
?* | *? | ?*? |
?/ | /? | ?/? |
?% | %? | ?%? |
備註
可為 Null 的運算子包含在命名空間 FSharp.Linq 的 NullableOperators 模組中。 可為 Null 的資料型別是 System.Nullable<'T>
。
在查詢運算式中,從允許 null 取代值的資料來源選取資料時,即會出現可為 Null 的型別。 在 SQL Server 資料庫中,資料表中每個資料行都有屬性指出是否允許 null。 如果允許 null,從資料庫傳回的資料可以包含 int
、float
等基本資料類型無法表示的 null。 因此,傳回的資料會以 System.Nullable<int>
取代 int
,且 System.Nullable<float>
取代 float
。 您可以使用 Value
屬性,從 System.Nullable<'T>
物件取得實際值,並可呼叫 HasValue
方法,判斷 System.Nullable<'T>
物件是否有值。 另一個適用的方法是 System.Nullable<'T>.GetValueOrDefault
方法,讓您可以取得適當類型的值或預設值。 預設值是不定格式的「零」值,例如 0、0.0 或 false
。
可為 Null 的型別可以使用 int
或 float
等一般轉換運算子,轉換為不可為 Null 的基本類型。 如果是可為 Null 的型別,您也可以使用轉換運算子,從一個可為 Null 的型別轉換為另一個可為 Null 的型別。 適當的轉換運算子名稱與標準運算子相同,但兩者位於不同模組,可為 Null 模組在 FSharp.Linq 命名空間中。 一般而言,使用查詢運算式時,您會開啟此命名空間。 在此情況下,您可以新增前置詞 Nullable.
至適當的轉換運算子,然後使用可為 Null 的轉換運算子,如下列程式碼所示。
open Microsoft.FSharp.Linq
let nullableInt = new System.Nullable<int>(10)
// Use the Nullable.float conversion operator to convert from one nullable type to another nullable type.
let nullableFloat = Nullable.float nullableInt
// Use the regular non-nullable float operator to convert to a non-nullable float.
printfn $"%f{float nullableFloat}"
輸出為 10.000000
。
另外,可為 Null 資料欄位上有查詢運算子 (例如 sumByNullable
) 可用於查詢運算式。 不可為 Null 型別的查詢運算子與可為 Null 的型別不相容,所以使用可為 Null 的資料值時,您必須使用可為 Null 版本的適當查詢運算子。 如需詳細資訊,請參閱查詢運算式。
下列範例示範使用 F# 查詢運算式中可為 Null 的運算子。 第一個查詢示範不使用可為 Null 的運算子時如何撰寫查詢;第二個查詢示範使用可為 Null 運算子的對等查詢。 如需完整內容,包括如何設定資料庫使用此程式碼範例,請參閱逐步解說:型別提供者存取 SQL Database。
open System
open System.Data
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
open Microsoft.FSharp.Linq
[<Generate>]
type dbSchema = SqlDataConnection<"Data Source=MYSERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;">
let db = dbSchema.GetDataContext()
query {
for row in db.Table2 do
where (row.TestData1.HasValue && row.TestData1.Value > 2)
select row
} |> Seq.iter (fun row -> printfn $"%d{row.TestData1.Value} %s{row.Name}")
query {
for row in db.Table2 do
// Use a nullable operator ?>
where (row.TestData1 ?> 2)
select row
} |> Seq.iter (fun row -> printfn "%d{row.TestData1.GetValueOrDefault()} %s{row.Name}")