SQL利用者にとって、「NULL」という予約語や、IS [NOT] NULL
という比較演算は、馴染みがあるところです。
NULLは、データが存在しないことである、と言ったりします。より正確には、値が存在しない状態を表しています。ここで、データと値の違いはどこにあり、なぜ後者がより正確なのでしょうか?「データ」という表現は曖昧に取れる一方、「値」という言葉には、数学でいうところのXの値という使い方に見られるように(もちろん、プログラミングでいうところの、変数の値、でもいいわけですが)、単にそれ自体で存在しているデータを超えた含意があります。データベースのコンテクストでいえば、テーブルスキーマにおけるカラムは、一定のデータ型を持ちますが、数値型であれば0、文字列型であれば空文字(長さ0の文字)のようなデータ型固有の表現とは別に、値そのものが存在していない状態がNULLで表現されます。
JSONにおいても、「フィールドの値が未定義」であることを意味する「null」という予約語が定義されています。一方、JSONのように、データ自体にデータ構造の情報が含まれる(データとは別にスキーマが存在していない)、データにあっては、「フィールドが未定義」の場合を考慮する必要があります。
MISSING
JSONデータに対して、N1QLによるクエリを実行した場合、他のドキュメントには存在するフィールドが、一部のドキュメントには存在しないことがあり得ます(RDB/SQLでは、テーブル内のすべてのレコードが同一のスキーマに従うため、このような状況が起こりません)。
N1QLには、そのようなギャップを埋めるため、MISSING
というキーワード(データ型)が用意されています。以下、N1QLにおけるデータ型としての、 NULL
とMISSING
の定義を確認した後に、N1QLにおける、存在しない値に対する比較演算について見ていきます。
データ型の側面から見た場合
MISSING
N1QLにおいてMISSING
は、JSONドキュメントでフィールド(名前と値のペア)が存在していない(欠落している)ことを表します。
N1QLにおけるSELECT文で、検索結果として返されるフィールドが存在しない(MISSINGである)データがある場合、(クエリ処理において、内部的にはMISSINGはリテラル式で扱われますが)、最終的な結果の配列中では、(JSONデータにおける未定義の値である)NULLに変換されます。
NULL
N1QLは、キーワードNULLを使用して空の値を表します。データ挿入、更新時に、フィールドの値をNULLにすることができます。
NULL値は、ゼロ除算や間違ったタイプの引数の受け渡しなど、特定の操作によっても生成され得ます。
NULLでは大文字と小文字が区別されません。たとえば、null、NULL、Null、およびnUllはすべて同等です。
存在しない値に対する比較演算
IS [NOT] NULL|MISSING
IS [NOT] NULL|MISSING
ファミリー演算子を使用すると、データ・セット内の属性の存在(または不在)に基づいて条件を指定できます。
これらは、データ型の定義から導かれる通りの挙動となります。
具体的なクエリと結果の例を見るのが、理解に役立つでしょう。
IS NULL
SELECT fname, children
FROM tutorial
WHERE children IS NULL
{
"results": [
{
"children": null,
"fname": "Fred"
}
]
}
IS MISSING
SELECT fname
FROM tutorial
WHERE children IS MISSING
{
"results": [
{
"fname": "Harry"
},
{
"fname": "Jane"
}
]
}
IS [NOT] VALUED
NULLとMISSINGは、JSONデータ上明らかに異なる状態であり、区別される必要がある一方、アプリケーションにおける検索条件としては区別する必要がない場合が考えられます。その際にANDやORを使って複数の検索条件を並置する代わりに、N1QLでは、IS [NOT] VALUED
という比較演算が利用可能です。
-
IS VALUED
は、値が'MISSING'でも'NULL'でもない場合、TRUE(真)になります。 -
IS NOT VALUED
は、値が'MISSING'あるいは'NULL'である場合、TRUE(真)になります。