見出し画像

[.NET][JavaScript][SQL] null と空文字の等価/不等価判定を言語別に並べて比較してみた

言語によって null や空文字の扱いは異なることがあります。
以下に例を示します。(★は注意が必要です)

■Equals

[C#]
Equals(null, null)
true

[VB.NET]
Equals(Nothing, Nothing)
True

■Is

[VB.NET]
(Nothing Is Nothing)
True

[JavaScript]
Object.is(null, null)
true

[SQL(ANSI/ISO 準拠)]
(NULL IS NULL)
TRUE

■Is Not

[VB.NET]
(Nothing IsNot Nothing)
False

[SQL(ANSI/ISO 準拠)]
(NULL IS NOT NULL)
FALSE

■null との等号比較

[C#]
(null == null)
true

[VB.NET]
(Nothing = Nothing)
True

[JavaScript]
(null === null)
true
(null == null)
true

[SQL(ANSI/ISO 準拠)]
★(NULL = NULL)
UNKNOWN
★NOT (@nullString = NULL)
UNKNOWN
※NOT しても UNKNOWN(以下同様)

■null との不等号比較

[C#]
(null != null)
false

[VB.NET]
(Nothing <> Nothing)
False

[JavaScript]
(null !== null)
false
(null != null)
false

[SQL(ANSI/ISO 準拠)]
(NULL <> NULL)
UNKNOWN

■空文字との等号比較

[C#]
(null == "")
false

[VB.NET]
★(Nothing = "")
True

[JavaScript]
(null === "")
false
(null == "")
false

[SQL(ANSI/ISO 準拠)]
(NULL = '')
UNKNOWN

■空文字との不等号比較

[C#]
(null != "")
true

[VB.NET]
★(Nothing <> "")
False

[JavaScript]
(null !== "")
true
(null != "")
true

[SQL(ANSI/ISO 準拠)]
★(NULL <> '')
UNKNOWN

■有効文字との等号比較

[C#]
(null == "a")
false

[VB.NET]
(Nothing = "a")
False

[JavaScript]
(null === "a")
false
(null == "a")
false

[SQL(ANSI/ISO 準拠)]
★(NULL = 'a')
UNKNOWN

■有効文字との不等号比較

[C#]
(null != "a")
true

[VB.NET]
(Nothing <> "a")
True

[JavaScript]
(null !== "a")
true
(null != "a")
true

[SQL(ANSI/ISO 準拠)]
★(NULL <> 'a')
UNKNOWN

■未定義値との等号比較

[JavaScript]
(null === undefined)
false
(null == undefined)
true

■未定義値との不等号比較

[JavaScript]
(null !== undefined)
true
(null != undefined)
false

ポイントは3つです。
・VB.NET では、String 型の等価/不等価演算子は Nothing と空文字を等しいと判断します。
・JavaScript では、非厳密演算子は null と undefined を等しいと判断します。
・ANSI/ISO 準拠のSQLでは、比較演算子による NULL との比較結果は UNKNOWN となります。(SQL Server で ANSI_NULLS オプションをOFFにすると違う結果になりますが、今後のバージョンでサポートされなくなることがアナウンスされています)

【注意】LINQ to Entities における null の扱い

LINQ to Entities の値比較における null の扱いには別途注意が必要です。
Entity Framework 6 で UseDatabaseNullSemantics プロパティ が導入され、既定(false)で (operand1 == operand2) が次のような複雑なSQL式に変換されるようになりました。
※operand1, operand2 がどちらも NULL となりうるケース、たとえば operand1 が NULL 許可列、operand2 が String 型変数の場合を想定します。

(((operand1 = operand2) AND (NOT (operand1 IS NULL OR operand2 IS NULL))) OR ((operand1 IS NULL) AND (operand2 IS NULL)))

どちらかが NULL の場合、ANSI 準拠の等価演算子 '=' では常に UNKNOWN が返されてしまうため、NULL を絡めた比較も正しく行われるような考慮がされています。
設定を true に変えれば (operand1 = operand2) という素直な式が生成されますが、NULL を正しく比較できないことを認識したうえで設定しないと「不可解な」挙動に頭を抱えることになりかねませんので注意しましょう。

この記事が気に入ったらサポートをしてみませんか?