ヌル(SQL)

ギリシャ語の小文字オメガ (ω)文字は、データベース理論では Null を表すために使用されます

SQLにおいてnullまたはNULL は、データベースにデータ値が存在しないことを示す特別なマーカーですリレーショナルデータベースモデルの考案者であるE. F. Coddによって導入された SQL null は、すべての真のリレーショナルデータベース管理システム ( RDBMS )が「欠落情報および適用不可能な情報」の表現をサポートするという要件を満たすために役立ちます。Codd はまた、データベース理論において null を表すためにギリシャ語の小文字オメガ(ω) 記号の使用を導入しました。SQL では、 は、このマーカーを識別するために使用される予約語です NULL

null を0値と混同しないでください。null は値がない状態を示し、ゼロ値とは異なります。例えば、「アダムは何冊の本を所有していますか?」という質問を考えてみましょう。答えは「ゼロ」(アダムが本を所有していないことは分かっている)または「null」(アダムが何冊所有しているかは分からない)になる可能性があります。データベーステーブルでは、この答えを報告する列は値なし(null でマーク)で始まり、アダムが本を所有していないことが確認されるまで、値ゼロに更新されることはありません。

SQLでは、nullは値ではなくマーカーです。この用法は、参照のnull値がどのオブジェクトも指していないことを意味する多くのプログラミング言語とは大きく異なります。

歴史

EF Codd は、1975 年にACM - SIGMODの FDT Bulletinに掲載された論文で、リレーショナル モデルで欠損データを表す方法として NULL について言及しています。SQL で採用されている NULL のセマンティクスとともに最もよく引用される Codd の論文は、1979 年にACM Transactions on Database Systemsに掲載された論文です。この論文で Codd はRelational Model/Tasmaniaも紹介していますが、後者の論文で提案されたその他の多くの点は不明瞭なままです。1979 年の論文のセクション 2.3 では、算術演算における NULL の伝播のセマンティクス、およびNULL と比較する際に3 値論理を使用する比較について詳しく説明されています。また、他の集合演算における NULL の扱いについても詳しく説明されています (後者の問題は現在でも議論の的となっています)。データベース理論の分野では、Codd (1975、1979) の元の提案は現在「Codd テーブル」と呼ばれています。[1]コッドは後に、1985年にComputerworld誌に掲載された2部構成の記事で、すべてのRDBMSが欠損データを示すNullをサポートするという要件を強化した[2] [3]

1986 年の SQL 標準では、IBM System Rでの実装プロトタイプの後に、基本的に Codd の提案が採用されました。Don Chamberlin は、NULL 値 (および重複行) が SQL の最も物議を醸す機能の 1 つであると認識していましたが、SQL における NULL 値の設計を擁護し、NULL 値は欠損情報に対するシステム サポートとしては最も安価な形式であり、多くの重複するアプリケーション レベルのチェック (半述語問題を参照) からプログラマを救い、同時に、データベース設計者が希望する場合は NULL 値を使用しないという選択肢も提供する (たとえば、よく知られている異常 (この記事のセマンティクスのセクションで説明)) という実際的な主張を持ち出しました。Chamberlin はまた、欠損値機能の提供以外に、NULL 値の実際的な経験から、特定のグループ化構造や外部結合など、NULL 値に依存する他の言語機能も生まれたと主張しました。最後に、彼は、実際には、ヌルは、既存のスキーマが本来の意図を超えて進化する必要がある場合に、欠落している情報ではなく適用できない情報をコード化することで、既存のスキーマを素早く修正する方法としても使用されると主張しました。たとえば、ガロンあたりの走行距離の列を持ちながら、電気自動車を迅速にサポートする必要があるデータベースなどです。[4]

コッドは1990年の著書『リレーショナル・モデル・データベース管理バージョン2』の中で、 SQL標準で義務付けられている単一のNullでは不十分であり、データが欠落している理由を示す2つの別々のNull型マーカーに置き換えるべきだと述べています。コッドの著書では、これら2つのNull型マーカーは「A値」と「I値」と呼ばれ、それぞれ「欠落しているが適用可能」と「欠落しているが適用不可能」を表しています。[5]コッドの勧告では、SQLのロジックシステムを拡張して4値ロジックシステムに対応する必要がありました。この複雑さが増すため、異なる定義を持つ複数のNullという概念は、データベース実務家の間では広く受け入れられていません。しかしながら、これは依然として活発な研究分野であり、現在も多数の論文が発表されています。

課題

NULLは、関連する3値論理(3VL)、 SQL結合における使用に関する特別な要件、そして集計関数とSQLグループ化演算子に必要な特別な処理のために、論争の的となり、議論の的となってきました。コンピュータサイエンス教授のロン・ファン・デル・メイデンは、これらの問題を次のように要約しています。「SQL標準における不整合は、SQLにおけるNULLの扱いに直感的な論理的意味論を当てはめることができないことを意味している。」[1]これらの問題を解決するための様々な提案がなされてきましたが、代替案の複雑さが、それらの広範な採用を阻んできました。

ヌル伝播

算術演算

Nullはデータ値ではなく、存在しない値を表すマーカーであるため、Nullに数学演算子を使用すると、Nullで表される未知の結果が生成されます。[6]次の例では、10にNullを掛けるとNullになります。

10 * NULL -- 結果はNULLです   

これは予期せぬ結果につながる可能性があります。例えば、Nullをゼロで割ろうとすると、プラットフォームは想定される「データ例外 - ゼロ除算」をスローする代わりに、Nullを返すことがあります。[6]この動作はISO SQL標準では定義されていませんが、多くのDBMSベンダーがこの操作を同様に扱っています。例えば、Oracle、PostgreSQL、MySQL Server、Microsoft SQL Serverの各プラットフォームは、以下の場合にすべてNullを返します。

NULL / 0  

文字列の連結

SQLで一般的な文字列連結演算も、オペランドの1つがNullの場合、Null結果になります。[7]次の例は、SQL文字列連結演算子でNullを使用した場合に返されるNull結果を示しています||

'Fish ' || NULL || 'Chips' -- 結果は NULL です     

これはすべてのデータベース実装に当てはまるわけではありません。例えば、Oracle RDBMSでは、NULLと空文字列は同じものとみなされるため、「Fish ' || NULL || 'Chips'」は「Fish Chips」になります。[8]

NULLと3値ロジック(3VL)との比較

Nullはどのデータドメインにも属さないため、「値」ではなく、未定義の値を示すマーカー(またはプレースホルダー)とみなされます。そのため、Nullとの比較では、TrueまたはFalseのいずれにもならず、常に3番目の論理結果であるUnknownが返されます。[9]値10とNullを比較する以下の式の論理結果はUnknownです。

SELECT 10 = NULL -- 結果は不明    

ただし、Null に対する特定の操作では、存在しない値が操作結果に関係しない場合でも、値を返すことがあります。次の例を考えてみましょう。

SELECT NULL OR TRUE -- 結果は True になります    

この場合、OR の左側の値が不明であるという事実は無関係です。左側の値に関係なく、OR 演算の結果は True になるからです。

SQLは3つの論理結果を実装するため、SQL実装では特殊な3値論理(3VL)を提供する必要があります。SQLの3値論理の規則は以下の表に示されています(pqは論理状態を表します) 。 [10] SQLがAND、OR、NOTに使用する真理値表は、KleeneとŁukasiewiczの3値論理の共通部分に対応しています(これらの論理は含意の定義が異なりますが、SQLではそのような演算は定義されていません)。[11]

pqpまたはqpqp = q
真実真実真実真実真実
真実間違い真実間違い間違い
真実未知真実未知未知
間違い真実真実間違い間違い
間違い間違い間違い間違い真実
間違い未知未知間違い未知
未知真実真実未知未知
未知間違い未知間違い未知
未知未知未知未知未知
ppではない
真実間違い
間違い真実
未知未知

WHERE句におけるUnknownの影響

SQLの3値ロジックは、データ操作言語(DML)のDML文およびクエリの比較述語で使用されます。この句により、DML文は述語がTrueと評価された行のみに作用します。述語がFalseまたはUnknownと評価された行は、 DML文、、またはクエリWHEREによって処理されず、破棄されます。UnknownとFalseを同じ論理結果として解釈することは、Nullを扱う際によく見られる誤りです。[10]次の簡単な例は、この誤りを示しています。INSERTUPDATEDELETESELECT

SELECT * FROM t WHERE i = NULL ;     

上記の例のクエリは、 i列とNullの比較で常にUnknownが返されるため、論理的には常に0行を返します。これは、 iがNullである行であっても同じです。Unknownの結果により、SELECTステートメントはすべての行を破棄します。(ただし、実際には、一部のSQLツールはNullとの比較を使用して行を取得します。)

NULL固有および3VL固有の比較述語

基本的なSQL比較演算子は、何かをNullと比較すると常にUnknownを返します。そのため、SQL標準ではNull専用の特別な比較述語を2つ提供しています。andIS NULL述語(接尾IS NOT NULL辞構文を使用)は、データがNullであるかどうかをテストします。[12]

SQL標準にはオプション機能F571「真理値テスト」が含まれており、3つの論理単項演算子(構文の一部である否定を含めると6つ)が追加されます。これらの演算子も接尾辞記法を用いて記述されます。これらの演算子の真理値表は以下のとおりです。[13]

ppは真であるpは真実ではないp は偽ですpは偽ではないpは不明ですpは不明ではない
真実真実間違い間違い真実間違い真実
間違い間違い真実真実間違い間違い真実
未知間違い真実間違い真実真実間違い

F571機能は、SQLにおけるブールデータ型の存在(本稿後述)とは直交しており、構文上の類似性があるにもかかわらず、F571はSQLにブール値や3値リテラルを導入するものではありません。F571機能は、 1999年にブールデータ型が標準に導入されるずっと以前からSQL92 [ 14]に存在していました。しかしながら、F571機能を実装しているシステムは限られており、PostgreSQLはその1つです。

SQLの3値ロジックの他の演算子にIS UNKNOWNを追加すると、SQLの3値ロジックは機能的に完全になります。[15]つまり、その論理演算子は(組み合わせて)考えられるあらゆる3値論理関数を表現できます。

F571 機能をサポートしていないシステムでは、式 p を Unknown にする可能性のあるすべての引数を調べて、それらの引数を IS NULL またはその他の NULL 固有の関数でテストすることにより、IS UNKNOWN p をエミュレートできますこれはより面倒になる可能性があります。

除外第4項の法則(WHERE句内)

SQLの三値論理において、排中律p OR NOT p)は、すべてのpに対して真と評価されなくなりました。より正確には、SQLの三値論理において、pがunknownの場合にのみp OR NOT pはunknownとなり、それ以外の場合には真となります。Nullとの直接比較はunknown論理値となるため、以下のクエリは

SELECT * FROM stuff WHERE ( x = 10 ) OR NOT ( x = 10 );                

SQLでは次のものとは等価ではない

SELECT * FROM stuff ;   

列 x に Null が含まれている場合、2 番目のクエリは 1 番目のクエリが返さない行、つまり x が Null である行をすべて返します。古典的な二値論理では、排中律により WHERE 句の述語を簡素化し、実質的には削除することができます。排中律を SQL の 3VL に適用しようとすると、事実上、誤った二分法になります。2 番目のクエリは実際には以下のクエリと同等です。

SELECT * FROM stuff ; -- は (3VL のため) 以下と同等です: SELECT * FROM stuff WHERE ( x = 10 ) OR NOT ( x = 10 ) OR x IS NULL ;                       

したがって、SQL の最初のステートメントを正しく簡略化するには、x が null ではないすべての行を返す必要があります。

SELECT * FROM stuff WHERE x IS NOT NULL ;        

上記を踏まえると、SQLのWHERE句では排中律に似たトートロジーが書けることに注意しましょう。IS UNKNOWN演算子が存在すると仮定すると、すべての述語pに対してp OR (NOT p ) OR ( p IS UNKNOWN)が真となります。論理学者の間では、これは排中律と呼ばれます

誤ったジレンマが発生する場所がわかりにくい SQL 式がいくつかあります。次に例を示します。

SELECT 'ok' WHERE 1 NOT IN ( SELECT CAST ( NULL AS INTEGER )) UNION SELECT 'ok' WHERE 1 IN ( SELECT CAST ( NULL AS INTEGER ));                   

行は生成されません。これは、IN引数セットの等価性の反復バージョンに変換され、1<>NULL は不明であり、1=NULL が不明であるのと同じです。(この例の CAST は、PostgreSQL などの一部の SQL 実装でのみ必要です。それ以外の場合は、型チェックエラーで拒否されます。多くのシステムでは、サブクエリで単純な SELECT NULL が機能します。)上記の例で不足しているケースは、もちろん次のとおりです。

SELECT 'ok' WHERE ( 1 IN ( SELECT CAST ( NULL AS INTEGER ))) IS UNKNOWN ;           

他の構成におけるNullとUnknownの影響

結合

結合はWHERE句と同じ比較規則を用いて評価されます。したがって、SQLの結合条件でNULL値許容列を使用する場合は注意が必要です。特に、NULL値を含むテーブルは、それ自体の自然な自己結合とは等しくありません。つまり、リレーショナル代数における任意のリレーションRでは が成り立ちますが、SQLの自己結合では、どこにでもNULL値を持つ行がすべて除外されます。[16]この動作の例は、NULL値の欠損値の意味を分析するセクションで示されています。

SQLCOALESCE関数またはCASE式は、結合条件におけるNull値の等価性を「シミュレート」するために使用できます。また、述語IS NULLIS NOT NULL述語を結合条件で使用することもできます。次の述語は、値AとBの等価性をテストし、Null値を等しいものとして扱います。

( A = B )または( ANULLかつBNULL )          

CASE式

SQLには2種類の条件式が用意されています。1つは「単純CASE」と呼ばれ、switch文のように動作します。もう1つは標準規格では「検索CASE」と呼ばれ、if...elseif文のように動作します。

単純CASE式では、DML句のNullに対するルールと同じルールに従って暗黙的な等価比較が行われますWHERE。したがって、単純CASE式ではNullの存在を直接確認することはできません。単純式でNullをチェックすると、CASE次の例のように常にUnknownという結果になります。

SELECT CASE i WHEN NULL THEN 'Is Null' -- これは返されませんWHEN 0 THEN 'Is Zero' -- i = 0 の場合に返されますWHEN 1 THEN 'Is One' -- i = 1 の場合に返されますEND FROM t ;                   

列ii = NULLにどのような値が含まれていても (Null が含まれていても)、式は Unknown と評価されるため、文字列は返されません。'Is Null'

一方、「検索」式では、条件式にandCASEなどの述語を使用できます。次の例は、検索式を使用してNull値を適切にチェックする方法を示しています。IS NULLIS NOT NULLCASE

SELECT CASE WHEN i IS NULL THEN 'Null Result' -- i が NULL の場合にこれが返されますWHEN i = 0 THEN 'Zero' -- i = 0 の場合にこれが返されますWHEN i = 1 THEN 'One' -- i = 1 の場合にこれが返されますEND FROM t ;                        

検索された式では、 iが Null であるすべての行のCASE文字列'Null Result'が返されます。

DECODEOracle の SQL 方言には、単純な CASE 式の代わりに使用でき、2 つの null を等しいと見なす組み込み関数が用意されています。

SELECT DECODE ( i NULL 'Null Result' 0 'Zero' 1 'One' ) FROM t ;         

最後に、これらすべての構成要素は、一致するものが見つからない場合は NULL を返します。これらにはデフォルトELSE NULL句があります。

手続き型拡張におけるIF文

SQL/PSM(SQL Persistent Stored Modules)は、SQL文などの手続き型IF拡張を定義しています。しかしながら、主要なSQLベンダーはこれまで独自の手続き型拡張を組み込んできました。ループや比較のための手続き型拡張は、DML文やクエリと同様のNull比較ルールに従って動作します。ISO SQL標準形式の以下のコードフラグメントは、IF文におけるNull 3VLの使用例を示しています。

IF i = NULL THEN SELECT '結果は True' ELSEIF NOT ( i = NULL ) THEN SELECT '結果は False' ELSE SELECT '結果は不明' ;              

このIF文は、比較結果がTrueと評価された場合のみアクションを実行します。比較結果がFalseまたはUnknownと評価された場合、IF文は制御を節に渡しELSEIF、最終的に節に渡します。Nullとの比較結果は常にUnknownと評価されるため、ELSE上記のコードの結果は常にメッセージになります。'Result is Unknown'

SQL Null欠損値セマンティクスの分析

T.イミエリンスキW.リプスキ・ジュニア(1984)[17]による画期的な研究は、欠損値意味論を実装するための様々な提案の意図された意味論を評価するための枠組みを提供しました。これはイミエリンスキ-リプスキ代数と呼ばれます。このセクションは、教科書「アリス」の第19章[18]にほぼ沿っています。同様の説明は、ロン・ファン・デル・メイデンのレビュー、§10.4にも掲載されています。[1]

選択と投影における弱い表現

Codd表のような欠損情報を表す構造は、実際にはパラメータの可能なインスタンス化ごとに1つの関係の集合を表すことを意図しています。Codd表の場合、これはNullを具体的な値に置き換えることを意味します。例えば、

 

従業員
名前
ジョージ43
ハリエットNULL
チャールズ56
エンプH22
名前
ジョージ43
ハリエット22
チャールズ56
エンプH37
名前
ジョージ43
ハリエット37
チャールズ56
Codd テーブルEmp は、図に示すように、関係EmpH22またはEmpH37 を表す場合があります。

コッド表などの構成は、その構成に対するクエリの回答を、それが表す関係(構成のモデルとみなされる)に対する対応するクエリの回答を得るために特定化できる場合、(欠損情報の)強い表現システムであると言われるより正確には、q が(「純粋な」関係の)リレーショナル代数におけるクエリ式であり、 q が欠損情報を表すことを意図した構成へのその持ち上げである場合、強い表現は、任意のクエリqと(表)構成Tに対して、q がすべての回答を構成に持ち上げるという特性を持つ。すなわち、

(上記は、任意の数のテーブルを引数として取るクエリにも当てはまるが、この議論では1つのテーブルに限定することで十分である。)選択と射影をクエリ言語の一部として考えると、明らかにコッドテーブルはこの強力な特性を持たない。例えば

SELECT * FROM Emp WHERE Age = 22 ;       

EmpH22のような関係が存在する可能性も考慮に入れるべきです。しかし、Codd表は「0行か1行のどちらかの結果」という論理和を表現することはできません。しかし、主に理論的な関心事である条件表(またはc表)と呼ばれる手法を使えば、そのような答えを表現することができます。

結果
名前状態
ハリエットω 1ω 1 = 22

ここで、条件列は、条件が偽の場合、行が存在しないと解釈されます。c-tableの条件列の式は任意の命題論理式になり得るため、c-tableが何らかの具体的な関係を表現しているかどうかという問題に対するアルゴリズムは共NP完全計算量を持ち、実用的価値がほとんどないことがわかります。

したがって、より弱い表現の概念が望ましい。イミエリンスキーとリプスキーは「弱い表現」という概念を導入した。これは本質的に、構成概念に対する(持ち上げられた)クエリが、確実な情報、すなわち構成概念のすべての「可能世界」のインスタンス化(モデル)に対して妥当な表現のみを返すことを可能にする。具体的には、構成概念が「弱い表現システム」であるのは、

上記の式の右辺は確実な情報、つまりデータベース内のNullをどのような値で置き換えてもデータベースから確実に抽出できる情報です。上で検討した例では、クエリ選択のすべての可能なモデルの積集合(つまり確実な情報)が実際には空であることが容易にわかります。これは、例えば(リフトされていない)クエリがリレーションEmpH37に対して行を返さないためです。より一般的には、ImielinskiとLipskiは、クエリ言語が射影、選択(および列名の変更)に制限されている場合、Coddテーブルは弱い表現システムであると示しました。しかし、次のセクションで示すように、クエリ言語に結合または和集合を追加すると、この弱い特性さえも失われます。WHERE Age = 22

結合や結合を考慮する場合: 弱い表現でさえも

前のセクションと同じ Codd テーブルEmpに対する次のクエリを検討してください。

SELECT Name FROM Emp WHERE Age = 22 UNION SELECT Name FROM Emp WHERE Age <> 22 ;              

Harriet の年齢にどのような具体的な値を選択するかに関係なく、上記のクエリはEmpNULLのあらゆるモデルの名前の完全な列を返しますが、(リフトされた) クエリがEmp自体に実行されると、Harriet は常に欠落します。つまり、次のようになります。

Empのクエリ結果:
名前
ジョージ
チャールズ
Empの任意のモデルに対するクエリ結果:
名前
ジョージ
ハリエット
チャールズ

したがって、クエリ言語にUNIONが追加されると、Coddテーブルは欠落情報の弱表現システムですらなくなり、つまり、それらに対するクエリは確実な情報をすべて報告しなくなるのです。ここで重要なのは、後のセクションで説明するNullに対するUNIONのセマンティクスが、このクエリでは考慮されていないということです。2つのサブクエリの「忘れやすい」性質によって、上記のクエリをCoddテーブルEmpに対して実行した際に、確実な情報の一部が報告されなかったのです。

自然結合の場合、確実な情報がクエリによっては報告されない可能性があることを示すために必要な例は、少し複雑になります。次の表を考えてみましょう。

J
F1F2F3
11NULL13
21NULL23
313233

そしてクエリ

SELECT F1 F3 FROM ( SELECT F1 F2 FROM J ) AS F12 NATURAL JOIN ( SELECT F2 F3 FROM J ) AS F23 ;                   
J のクエリ結果:
F1F3
3133
J の任意のモデルでのクエリ結果:
F1F3
1113
2123
3133

上記で何が起きるかの直感は、サブクエリ内の射影を表す Codd テーブルが、列 F12.F2 と F23.F2 の Null が実際にはテーブル J 内のオリジナルのコピーであるという事実を見失っているということです。この観察から、Codd テーブルを比較的簡単に改善するには (この例では正しく機能しますが)、単一の NULL シンボルの代わりに、スコーレム定数(つまり、定数関数でもあるスコーレム関数)、たとえば ω 12と ω 22 を使用することだと考えられます。v テーブルまたは Naive テーブルと呼ばれるこのようなアプローチは、上で説明した c テーブルよりも計算コストが低くなります。ただし、v テーブルは選択で否定を使用しない (差集合も使用しない) クエリの弱い表現にすぎないという意味で、これはまだ不完全情報に対する完全なソリューションではありません。このセクションで検討する最初の例は、否定選択句 を使用しているため、v テーブル クエリが確実な情報を報告しない例でもあります。WHERE Age <> 22

チェック制約と外部キー

SQLの3値ロジックがSQLデータ定義言語(DDL)と交差する主な箇所は、チェック制約の形式です。列に設定されたチェック制約は、DMLWHERE句のルールとは少し異なるルールセットに従って動作します。DML句WHEREは行に対してTrueと評価される必要がありますが、チェック制約はFalseと評価されてはなりません(ロジックの観点からは、指定される値はTrueとUnknownです)。つまり、チェック制約は、チェックの結果がTrueまたはUnknownのいずれかであれば成功します。次のチェック制約の例では、列iに整数値が挿入されることを禁止しますが、チェックの結果がNullに対して常にUnknownと評価されるため、Nullの挿入は許可します。[19]

テーブルtを作成します( i がINTEGER で制約ck_iがチェックされます( i < 0かつi = 0かつi > 0 ) );                      

WHERE句に対する指定値の変化により、論理的な観点からは、排中律はCHECK制約のトートロジーとなり、常に成立することを意味します。さらに、NULLを存在するが未知の値として解釈すると、上記のような一部の異常なCHECKでは、NULL以外の値で置き換えることのできないNULLの挿入を許してしまいます。CHECK (p OR NOT p)

列にNULL値を拒否するよう制約するには、NOT NULL以下の例に示すように制約を適用します。この制約は、述語を含むチェック制約NOT NULLと意味的に同等ですIS NOT NULL

テーブルtを作成します( i INTEGER NOT NULL );        

デフォルトでは、外部キーのチェック制約は、キーのフィールドのいずれかがNULLの場合に成功します。例えば、次の表は

CREATE TABLE Books ( title VARCHAR ( 100 )、author_last VARCHAR ( 20 )、author_first VARCHAR ( 20 )、FOREIGN KEY ( author_last author_first ) REFERENCES Authors ( last_name first_name ));              

NULLは、Authors テーブルの定義方法やテーブルに含まれる内容に関係なく、author_last または author_first がある行の挿入を許可します。より正確には、これらのフィールドのいずれかが null の場合、Authors テーブルにないフィールドであっても、もう一方のフィールドには任意の値が許可されます。たとえば、Authors に のみが含まれている場合('Doe', 'John')、 は('Smith', NULL)外部キー制約を満たします。SQL -92 では、このような場合に一致を絞り込むための 2 つのオプションが追加されました。宣言MATCH PARTIALの後に が追加された場合REFERENCES、null 以外の値はすべて外部キーと一致する必要があります。たとえば、('Doe', NULL)はまだ一致しますが、 は一致('Smith', NULL)しません。最後に、MATCH FULLが追加された場合('Doe', NULL)、 も制約と一致しませんが、(NULL, NULL)はまだ一致します。

外部結合

結果セットにNullプレースホルダーを含むSQL 外部結合クエリの例。NullマーカーはNULL、結果セット内のデータの代わりに「in place」という単語で表されます。結果はMicrosoft SQL Serverから取得され、SQL Server Management Studioに表示されます。

SQL外部結合(左外部結合、右外部結合、完全外部結合を含む)は、関連テーブル内の欠損値のプレースホルダーとして自動的にNULL値を生成します。例えば左外部結合では、演算子の右側に現れるテーブルから欠損している行の代わりにNULL値が生成されますLEFT OUTER JOIN。以下の簡単な例では、2つのテーブルを用いて、左外部結合におけるNULLプレースホルダーの生成方法を示します。

最初のテーブル ( Employee ) には従業員 ID 番号と名前が含まれており、2 番目のテーブル ( PhoneNumber ) には関連する従業員 ID 番号と電話番号が含まれています(以下を参照)。

従業員
ID苗字ファーストネーム
1ジョンソンジョー
2ルイスラリー
3トンプソントーマス
4パターソンパトリシア
電話番号
ID番号
1555-2323
3555-9876

次のサンプル SQL クエリは、これら 2 つのテーブルに対して左外部結合を実行します。

SELECT e.ID e.LastName e.FirstName pn.Number FROM Employee e LEFT OUTER JOIN PhoneNumber pn ON e.ID = pn.ID ;             

このクエリによって生成された結果セットは、次に示すように、 SQL が右側のテーブル ( PhoneNumber ) に存在しない値のプレースホルダーとして Null を使用する方法を示しています。

クエリ結果
ID苗字ファーストネーム番号
1ジョンソンジョー555-2323
2ルイスラリーNULL
3トンプソントーマス555-9876
4パターソンパトリシアNULL

集計関数

SQLでは、サーバー側でのデータの集計計算を簡素化するために集計関数COUNT(*)が定義されています。この関数を除くすべての集計関数はNull除去処理を実行するため、計算の最終結果にはNullは含まれません。[20]

Null の除去は、Null をゼロに置き換えることと同じではないことに注意してください。例えば、次の表では、AVG(i)( の値の平均i)は の結果とは異なりますAVG(j)

j
150150
200200
250250
NULL0

ここでAVG(i)は200(150、200、250の平均)であり、AVG(j)は150(150、200、250、0の平均)です。この副作用としてよく知られているのは、SQLでははではなく とAVG(z)等価になるということです[4]SUM(z)/COUNT(*)SUM(z)/COUNT(z)

集計関数の出力はNullになることもあります。以下に例を示します。

SELECT COUNT ( * ), MIN ( e . Wage ), MAX ( e . Wage ) FROM Employee e WHERE e . LastName LIKE '%Jones%' ;        

このクエリは常に1行だけを出力し、姓に「Jones」を含む従業員の数と、それらの従業員の最低賃金と最高賃金を示します。しかし、指定された条件に該当する従業員がいない場合はどうなるでしょうか?空集合の最小値または最大値を計算することは不可能であるため、結果はNULL、つまり答えがないことを示す値になります。これは不明な値ではなく、値が存在しないことを示すNull値です。結果は以下のようになります。

カウント(*)MIN(e.賃金)MAX(e.賃金)
0NULLNULL

2つのヌルが等しい場合: グループ化、ソート、およびいくつかの集合演算

SQL:2003では、すべてのNullマーカーは互いに等しくないと定義されているため、特定の操作を実行する際にNullをグループ化するには特別な定義が必要でした。SQLでは、「互いに等しい2つの値、または任意の2つのNull」を「区別できない」と定義しています。[21]この区別できないという定義により、SQLでは句(またはグループ化を実行する他のSQL言語機能)を使用することで、Nullをグループ化および並べ替えることができますGROUP BY

Null の処理に「not distinct」定義を使用するその他の SQL 操作、句、およびキーワードには次のものがあります。

  • PARTITION BYランキング関数とウィンドウ関数の節はROW_NUMBER
  • UNION、、INTERSECTおよび演算子EXCEPT、行の比較/削除の目的で NULL を同じものとして扱います。
  • クエリDISTINCTで使用されるキーワードSELECT

NULL同士は等しくない(結果はUnknownである)という原則はUNION、SQL仕様の演算子において実質的に違反している。この演算子はNULL同士を識別している。[1]その結果、SQLにおける集合演算(例えば、和集合演算や差集合演算など)の一部は、NULLとの明示的な比較を伴う演算(例えば、前述の句内の演算)とは異なり、確実な情報を表さない結果を生成する可能性があるWHERE。1979年のCoddの提案(SQL92で採用された)では、この意味上の矛盾は、集合演算における重複の除去は「検索演算の評価における等価性テストよりも低い詳細レベルで行われる」という主張によって合理化されている。[11]

SQL標準では、NULL値のデフォルトのソート順序は明示的に定義されていません。代わりに、準拠システムでは、リストNULLS FIRSTor句を使用することで、NULL値をすべてのデータ値の前または後にソートすることができます。ただし、すべてのDBMSベンダーがこの機能を実装しているわけではありません。この機能を実装していないベンダーは、DBMSにおけるNULL値のソート処理を別途指定する場合があります。[19]NULLS LASTORDER BY

インデックス操作への影響

一部のSQL製品では、NULLを含むキーをインデックス化しません。例えば、PostgreSQLバージョン8.3以前では、 Bツリーインデックスのドキュメントには次のように記載されていました。[22]

Bツリーは、何らかの順序でソート可能なデータに対する等価性検索と範囲検索を処理できます。特に、PostgreSQLのクエリプランナーは、インデックス付き列が以下の演算子のいずれかを用いた比較に関係する場合、Bツリーインデックスの使用を検討します。< ≤ = ≥ >

これらの演算子の組み合わせに相当する構造(BETWEEN や IN など)も、B ツリー インデックス検索を使用して実装できます。(ただし、IS NULL は = と同等ではなく、インデックスを作成できないことに注意してください。)

インデックスが一意性を強制する場合、NULLはインデックスから除外され、NULL間の一意性は強制されません。ここでもPostgreSQLのドキュメントから引用します。[23]

インデックスが一意であると宣言されている場合、同じインデックス値を持つ複数のテーブル行は許可されません。NULLは等しいとはみなされません。複数列の一意インデックスでは、2つの行のインデックス列のすべてが等しい場合のみ、拒否されます。

これは、SQL:2003で定義されたスカラー Null 比較の動作と一致しています。

NULLをインデックス化する別の方法としては、SQL:2003で定義された動作に従って、 NULLを区別できないものとして扱う方法があります。例えば、 Microsoft SQL Serverのドキュメントには次のように記載されています。[24]

インデックス作成において、NULLは等しいとみなされます。したがって、キーが複数の行でNULLの場合、一意インデックス(UNIQUE制約)を作成できません。一意インデックスまたは一意制約の列を選択する際は、NOT NULLとして定義されている列を選択してください。

これらのインデックス戦略はどちらも、SQL:2003で定義されたNULLの動作と一致しています。SQL:2003標準ではインデックス手法が明示的に定義されていないため、NULLに対するインデックス戦略の設計と実装はベンダーに完全に委ねられています。

null処理関数

SQLでは、Nullを明示的に処理するための2つの関数が定義されています。NULLIFと ですCOALESCE。どちらの関数も検索CASEの略語です。[25]

NULLIF

このNULLIF関数は2つのパラメータを受け取ります。最初のパラメータが2番目のパラメータと等しい場合はNULLIFNullを返します。それ以外の場合は、最初のパラメータの値を返します。

NULLIF (値1 ,値2 ) 

したがって、NULLIFは次の式の略語になりますCASE

値1 =値2の場合NULL そうでない場合値1終了         

合体

このCOALESCE関数はパラメータのリストを受け入れ、リストから最初の Null 以外の値を返します。

COALESCE (値1 値2 値3 ...)   

COALESCEは、次の SQLCASE式の省略形として定義されています。

CASE値1 がNULLでない場合1値2 がNULLでない場合2 値3 がNULLでない場合3 ... END                       

一部の SQL DBMS では、 に類似したベンダー固有の関数が実装されていますCOALESCE。一部のシステム ( Transact-SQLなど)ではISNULL、 関数、または と機能的に類似したその他の関数が実装されていますCOALESCE。( Transact-SQL の関数の詳細については、Is関数をIS参照してください。)

NVL

OracleNVL関数は2つのパラメータを受け入れます。最初の非NULLパラメータを返します。すべてのパラメータがNULLの場合はNULLを返します。

式は次のようにCOALESCE同等の式に変換できますNVL

COALESCE ( val1 , ... , val { n } )      

次のように変換されます:

NVL ( val1 , NVL ( val2 , NVL ( val3 , , NVL ( val { n - 1 } , val { n } ) )))                  

この関数の使用例は、式内の NULL を、次のようにNVL(SALARY, 0)SALARYが NULL の場合は値 0 に置き換える」という値に置き換えることです。

ただし、注目すべき例外が1つあります。ほとんどの実装では、 はCOALESCE最初の非NULLパラメータに到達するまでパラメータを評価しますが、 はすべてのパラメータを評価します。これはいくつかの理由から重要です。最初の非NULLパラメータの後のNVLパラメータは関数である可能性があり、計算コストが高くなったり、無効になったり、予期しない副作用を引き起こしたりする可能性があります。

NullとUnknownのデータ型

SQLではリテラルNULL 型指定されていません。つまり、整数、文字、またはその他の特定のデータ型として指定されていません。[26]このため、Nullを特定のデータ型に明示的に変換することが必須(または望ましい)となる場合があります。例えば、 RDBMSがオーバーロードされた関数をサポートしている場合、SQLはNullが渡されるパラメータを含むすべてのパラメータのデータ型を知らなければ、正しい関数を自動的に解決できない可能性があります。

リテラルからNULL特定の型の Null への変換は、SQL-92CASTで導入された を使用することで可能です。例:

CAST ( NULLINTEGERとして)   

INTEGER 型の存在しない値を表します。

Unknownの実際の型付け(NULL自体と区別できるかどうか)はSQL実装によって異なります。例えば、次のようになります。

SELECT 'ok' WHERE ( NULL <> 1 ) IS NULL ;       

NULL ブール値を Unknown と統合する一部の環境 ( SQLitePostgreSQLなど) では解析と実行に成功しますが、他の環境 ( SQL Server Compactなど) では解析に失敗します。この点ではMySQLもPostgreSQLと同様に動作します(ただし、 MySQL ではTRUE と FALSE が通常の整数 1 と 0 と区別されないという小さな例外があります)。PostgreSQL はさらにIS UNKNOWN、3 値の論理結果が Unknown かどうかをテストするために使用できる述語を実装していますが、これは単なる構文糖です。

BOOLEANデータ型

ISO SQL:1999規格ではSQLにBOOLEANデータ型が導入されましたが、これはまだオプションの非コア機能であり、コードT031となっています。[27]

制約によって制限されている場合NOT NULL、SQL BOOLEAN は他の言語のブール型と同様に機能します。ただし、制約がない場合、BOOLEAN データ型はその名前にもかかわらず、真理値 TRUE、FALSE、UNKNOWN を保持できます。これらはすべて、標準規格ではブール値リテラルとして定義されています。また、標準規格では、NULL と UNKNOWN は「全く同じ意味として互換的に使用できる」とされています。[28] [29]

ブール型は、特にUNKNOWNリテラルの強制的な動作のために批判の対象となってきた。UNKNOWNリテラルはNULLと同一視されるため、それ自身と決して等しくならない。[30]

上で述べたように、PostgreSQLSQL実装では、UNKNOWN BOOLEANを含むすべてのUNKNOWN結果を表すためにNullが使用されます。PostgreSQLはUNKNOWNリテラルを実装していません(ただし、直交機能であるIS UNKNOWN演算子は実装しています)。他の主要ベンダーのほとんどは、2012年時点でブール型(T031で定義)をサポートしていません。[31]ただし、OracleのPL/SQLの手続き型部分はBOOLEAN変数をサポートしています。これらの変数にもNULLを割り当てることができ、その値はUNKNOWNと同じとみなされます。[32]

論争

よくある間違い

Null の動作に関する誤解は、ISO 標準 SQL 文と実際のデータベース管理システムでサポートされている特定の SQL 方言の両方において、SQL コードにおける多数のエラーの原因となっています。これらの間違いは通常、Null と 0 (ゼロ) または空文字列 (長さがゼロの文字列値で、SQL では と表現されます'') との混同によって生じます。ただし、SQL 標準では、Null は空文字列や数値 とは異なるものとして定義されています0。Null は値が存在しないことを示しますが、空文字列と数値のゼロはどちらも実際の値を表します。

典型的なエラーとして、equals演算子を=キーワードと組み合わせてNULLNull行を検索しようとすることが挙げられます。SQL標準では、これは無効な構文であり、エラーメッセージまたは例外が発生します。しかし、ほとんどの実装ではこの構文が受け入れられ、このような式は と評価されます。その結果、Null行の有無にかかわらず、行は見つかりません。Null行を取得するには、の代わりにUNKNOWN述語 を使用する方法が提案されていますIS NULL= NULL

SELECT * FROM sometable WHERE num = NULL ; -- 「WHERE num IS NULL」とすべき      

関連はあるものの、より微妙な例として、WHERE句または条件文で列の値を定数と比較することがあります。そのフィールドにNull値が含まれている場合、欠損値は定数より「小さい」または「等しくない」と誤って想定されることがよくありますが、実際にはそのような式はUnknownを返します。以下に例を示します。

SELECT * FROM sometable WHERE num <> 1 ; -- 多くのユーザーの予想に反して、num が NULL の行は返されません       

これらの混乱は、SQLのロジックにおいて同一性則が制限されているため発生します。NULLリテラルまたは真理値を用いた等価比較を扱う場合、SQLは常に式の結果としてUNKNOWN返されます。これは部分的な同値関係であり、SQLは非反射的論理の一例となります[33]UNKNOWN

同様に、Nullは空文字列と混同されることがよくあります。LENGTH文字列の文字数を返す関数を考えてみましょう。この関数にNullが渡されると、関数はNullを返します。ユーザーが3値ロジックに精通していない場合、予期しない結果につながる可能性があります。以下に例を示します。

SELECT * FROM sometable WHERE LENGTH ( string ) < 20 ; -- string が NULL の行は返されません。      

一部のデータベース インターフェイス プログラム (または Oracle のようなデータベース実装) では、NULL が空の文字列として報告され、空の文字列が誤って NULL として保存される可能性があるという事実により、状況は複雑になります。

批判

ISO SQLにおけるNullの実装は、批判、議論、そして変更を求める声の対象となっている。『The Relational Model for Database Management: Version 2』において、コッドはSQLにおけるNullの実装には欠陥があり、2つの異なるNull型マーカーに置き換えるべきだと提言した。彼が提案したマーカーは、「欠落しているが適用可能」「欠落しているが適用不可能」を表すもので、それぞれA値I値と呼ばれる。コッドの提言が受け入れられた場合、SQLに4値ロジックを実装する必要があった。[5]また、コッドの提言にNull型マーカーを追加し、データ値が「欠落」となる理由をさらに多く示すことを提案する者もいるが、これはSQLのロジックシステムの複雑さを増大させる。SQLに複数のユーザー定義Nullマーカーを実装するという提案も、これまで何度もなされてきた。しかし、複数のNullマーカーをサポートするために必要なNull処理とロジックシステムの複雑さのため、これらの提案はいずれも広く受け入れられていない。

『第三の宣言』の著者であるクリス・デイトヒュー・ダーウェンは、 SQLのNull実装は本質的に欠陥があり、完全に排除されるべきだと提言している。[34] SQLのNull処理の実装(特に集計関数)における不整合や欠陥を指摘し、Nullの概念自体に欠陥があり、リレーショナルモデルから削除されるべきだとしている。[35]ファビアン・パスカルのような他の研究者は、「関数の計算において欠損値をどのように扱うべきかは、リレーショナルモデルによって規定されるものではない」という信念を述べている。[要出典]

閉世界仮説

ヌルに関するもう一つの論点は、ヌルがリレーショナルデータベースの閉世界仮定モデルに開世界仮定を導入することで、そのモデルに違反しているという点です。[36]データベースにおける閉世界仮定とは、「データベースによって明示的または暗黙的に示されるすべてのものは真であり、それ以外のすべては偽である」というものです。[37]この見解は、データベースに格納される世界に関する知識が完全であると仮定しています。しかし、ヌルは開世界仮定に基づいて動作します。開世界仮定では、データベースに格納される一部の項目は未知とみなされるため、データベースに格納される世界に関する知識は不完全になります。

参照

参考文献

  1. ^ abcd Ron van der Meyden、「不完全情報への論理的アプローチ:概観」、Jan Chomicki; Gunter Saake(編)『データベースと情報システムの論理』、Kluwer Academic Publishers ISBN 978-0-7923-8129-7、p. 344; PSプレプリント(注:プレプリントのページ番号は出版版と異なります)
  2. ^ Codd, EF (1985年10月14日). 「あなたのデータベースは本当にリレーショナルですか?」Computerworld .
  3. ^ Codd, EF (1985年10月21日). 「DBMSはルールに従って動作していますか?」Computerworld .
  4. ^ ab ドン・チェンバーリン (1998). DB2ユニバーサルデータベース完全ガイド. モーガン・カウフマン. pp.  28– 32. ISBN 978-1-55860-482-7
  5. ^ ab Codd, EF (1990). 『データベース管理のためのリレーショナルモデル(第2版)』Addison Wesley Publishing Company . ISBN 978-0-201-14192-4
  6. ^ ab ISO/IEC (2003). ISO/IEC 9075-2:2003, "SQL/Foundation" . ISO/IEC. セクション6.2.6:数値式.
  7. ^ ISO/IEC (2003). ISO/IEC 9075-2:2003, "SQL/Foundation" . ISO/IEC. セクション6.2.8:文字列値式.
  8. ^ 「OracleからPostgreSQLへの移行時に空の文字列を処理する | AWSデータベースブログ」。aws.amazon.com . 2022年5月23日. 2023年12月30日閲覧
  9. ^ ISO/IEC (2003). ISO/IEC 9075-1:2003, "SQL/Framework". ISO/IEC. セクション4.4.2: NULL値.
  10. ^ ab Coles, Michael (2005年6月27日). 「NULLに関する4つのルール」. SQL Server Central . Red Gate Software.
  11. ^ ab Hans-Joachim, K. (2003). 「リレーショナルデータベースにおけるヌル値と確実な情報回答」.データベースにおけるセマンティクス. 第2回国際ワークショップ ダグストゥール城(ドイツ)、2001年1月7日~12日. 改訂論文. コンピュータサイエンス講義ノート. 第2582巻. pp.  119– 138. doi :10.1007/3-540-36596-6_7. ISBN 978-3-540-00957-3
  12. ^ ISO/IEC (2003). ISO/IEC 9075-2:2003, "SQL/Foundation" . ISO/IEC. セクション8.7: null述語.
  13. ^ CJ Date (2004)、『データベースシステム入門』第8版、ピアソンエデュケーション、594ページ
  14. ^ メルトン、ジム、サイモン、アラン・R. (1993). 『新しいSQLを理解する:完全ガイド』 モーガン・カウフマン. pp.  145– 147. ISBN 978-1-55860-245-8
  15. ^ CJ Date,リレーショナルデータベース著作集, 1991-1994 , Addison-Wesley, 1995, p. 371
  16. ^ CJ Date (2004)、『データベースシステム入門』第8版、ピアソンエデュケーション、584ページ
  17. ^ Imieliński, T. ; Lipski, W. Jr. (1984). 「リレーショナルデータベースにおける不完全な情報」Journal of the ACM . 31 (4): 761– 791. doi : 10.1145/1634.1886 . S2CID  288040.
  18. ^ アビテブール、セルジュ、ハル、リチャード・B、ヴィアヌ、ビクター(1995). 『データベースの基礎』 . アディソン・ウェズリー. ISBN 978-0-201-53771-0
  19. ^ ab Coles, Michael (2007年2月26日). 「NullとNull?」. SQL Server Central . Red Gate Software.
  20. ^ ISO/IEC (2003). ISO/IEC 9075-2:2003, 「SQL/Foundation」 . ISO/IEC. セクション4.15.4:集計関数.
  21. ^ ISO/IEC (2003). ISO/IEC 9075-2:2003, "SQL/Foundation" . ISO/IEC. セクション3.1.6.8:定義: distinct .
  22. ^ 「PostgreSQL 8.0.14ドキュメント:インデックスの種類」。PostgreSQL 。 2008年11月6日閲覧
  23. ^ 「PostgreSQL 8.0.14 ドキュメント: ユニークインデックス」. PostgreSQL . 2008年11月6日閲覧
  24. ^ 「ユニークインデックスの作成」PostfreSQL、2007年9月。 2008年11月6日閲覧
  25. ^ ISO/IEC (2003). ISO/IEC 9075-2:2003, 「SQL/Foundation」 . ISO/IEC. セクション6.11: case式.
  26. ^ メルトン、ジム、サイモン、アラン・R. (2002). SQL:1999: リレーショナル言語コンポーネントの理解. モーガン・カウフマン. p. 53. ISBN 978-1-55860-456-8
  27. ^ 「ISO/IEC 9075-1:1999 SQL標準」。ISO。1999年。 {{cite web}}:欠落または空|url=(ヘルプ)
  28. ^ Date, C. (2011). SQLとリレーショナル理論:正確なSQLコードの書き方. O'Reilly Media, Inc. p. 83. ISBN 978-1-4493-1640-2
  29. ^ ISO/IEC 9075-2:2011 §4.5
  30. ^ Prigmore, Martyn (2007). 『Webアプリケーションによるデータベース入門』Pearson Education Canada. p. 197. ISBN 978-0-321-26359-9
  31. ^ Troels Arvin、BOOLEANデータ型の実装の調査
  32. ^ スティーブン・フォイヤーシュタイン、ビル・プリビル (2009). 『Oracle PL/SQLプログラミング』 O'Reilly Media, Inc. pp. 74, 91. ISBN 978-0-596-51446-4
  33. ^ Arenhart、Krause (2012)、「古典的論理か非再帰的論理か? 意味論的過小決定の事例」、Revista Portuguesa de Filosofia68 (1/2): 73–86doi :10.17990/RPF/2012_68_1_0073、JSTOR  41955624
  34. ^ ヒュー・ダーウェンクリス・デイト「第三の宣言」thethirdmanifesto.com . 2007年5月29日閲覧
  35. ^ ダーウェン、ヒュー. 「The Askew Wall」(PDF) . dcs.warwick.ac.uk . 2007年5月29日閲覧
  36. ^ Date, Chris (2005年5月). 『データベースの奥深さ:実践者のためのリレーショナル理論』 O'Reilly Media, Inc. p. 73. ISBN 978-0-596-10012-4
  37. ^ Date, Chris . 「要約:閉世界仮説」.データ管理協会サンフランシスコ・ベイエリア支部. 2007年5月19日時点のオリジナルよりアーカイブ2007年5月29日閲覧。

さらに読む

  • EF Codd. 関係性の理解(第7回). FDT Bulletin of ACM-SIGMOD, 7(3-4):23–28, 1975.
  • Codd, EF (1979). 「データベースリレーショナルモデルの拡張による意味の獲得」. ACM Transactions on Database Systems . 4 (4): 397– 434. CiteSeerX  10.1.1.508.5701 . doi :10.1145/320107.320109. S2CID  17517212.特に§2.3。
  • Date, CJ (2000). 『データベース・リレーショナル・モデル:回顧的レビューと分析:EF Coddのデータベース技術分野への貢献に関する歴史的説明と評価』Addison Wesley Longman . ISBN 978-0-201-61294-3
  • Klein, Hans-Joachim (1994). 「確実な回答を保証するためのSQLクエリの修正方法」ACM SIGMOD Record . 23 (3): 14– 20. doi : 10.1145/187436.187445 . S2CID  17354724.
  • Claude Rubinson、「SQLにおけるNull、3値論理、曖昧性:Dateの批判に対する批判」、Wayback Machineに2016年3月5日アーカイブ、SIGMOD Record、2007年12月(第36巻、第4号)
  • John Grant, SQLにおけるNull値。SIGMOD Record、2008年9月(第37巻、第3号)
  • Waraporn、Narongrit、Kriengkrai Porkaew. 「サブクエリとアトミック述語のNullセマンティクス」IAENG International Journal of Computer Science 35.3 (2008): 305-313.
  • Thalheim, Bernhard; Schewe, Klaus-Dieter (2011). 「NULL '値' 代数と論理」.人工知能とその応用の最前線. 225 (情報モデリングと知識ベース XXII). doi :10.3233/978-1-60750-690-4-354.
  • Enrico FranconiとSergio Tessaris、「SQL Nullの論理について」、第6回Alberto Mendelzon国際データ管理基礎ワークショップ議事録、ブラジル、Ouro Preto、2012年6月27~30日、pp. 114~128
  • Oracle NULLs アーカイブ 2013-04-12 at the Wayback Machine
  • 第三の宣言
  • データの順序付けにおけるNULLの影響
  • JDBC が null と空文字列を区別しないという Java のバグレポート。Sun はこれを「バグではない」としてクローズしました。
「https://en.wikipedia.org/w/index.php?title=Null_(SQL)&oldid=1322000533」から取得