リレーショナルデータベースではnull値を許可すべきではないという考え方があります。つまり、テーブルの属性(列)でnull値を許可しないようにする必要があります。ソフトウェア開発のバックグラウンドから来て、私はこれを本当に理解していません。属性のコンテキスト内でnullが有効な場合は、許可する必要があるようです。これは、オブジェクト参照がnullであることが多いJavaでは非常に一般的です。データベースの豊富な経験がないので、ここで何かが足りないのではないかと思います。
33 に答える
ヌルは、データベースの正規化の観点から否定的に見られます。値がゼロになる可能性がある場合は、値を持たないアイテムの行を必要としないように、実際にはそれを別のスパーステーブルに分割する必要があるという考え方です。
すべてのデータが有効で価値があることを確認するための努力です。
ただし、パフォーマンス上の理由でさらに別の結合を回避したい場合は特に、nullフィールドがあると便利な場合があります(ただし、データベースエンジンが適切に設定されていれば、非常に高性能なシナリオを除いて、これは問題にはなりません)。
-アダム
ヌルに対する反論の 1 つは、明確に定義された解釈がないということです。フィールドが null の場合、次のいずれかとして解釈される可能性があります。
- 値は「なし」または「空のセット」です
- そのフィールドに意味のある値はありません。
- 値は不明です。
- 値はまだ入力されていません。
- 値は空の文字列です (null と空の文字列を区別しないデータベースの場合)。
- 一部のアプリケーション固有の意味 (たとえば、「値が null の場合は、既定値を使用します。」)
- エラーが発生したため、フィールドが null 値になってはならないのに、null 値になっています。
一部のスキーマ設計者は、すべての値とデータ型の解釈が明確に定義されている必要があるため、null は不適切です。
場合によります。
NULL
データベースで s を許可する理由(選択は列ごとに行う必要があります) と、それらをどのように解釈、無視、またはその他の方法で処理するかを理解している限り、それらは問題ありません。
たとえば、NUM_CHILDREN
「答えがわからない場合はどうしますか」のような列は、 NULL
. NUM_CHILDREN
私の考えでは、この列の設計に最適なオプションは他にありません (列が有効かどうかを判断するためのフラグがあったとしても、この列には値が必要です)。
一方、NULL
s を許可せず、特定の場合 (フラグの代わりに) 特別に予約された値 (実際には不明な場合の子の数の -1 など) がある場合は、同様の方法でこれらに対処する必要があります。規約、文書など
したがって、最終的には、規則、文書化、および一貫性をもって問題に対処する必要があります。
上記の回答でAdam Davisが明らかに支持しているように、列をスパース(またはNUM_CHILDREN
ほとんどのデータに既知の値がある例の場合はそれほどスパースではない)テーブルに正規化する代わりに、すべての NULL を排除することは、一般的な慣行では実行できません。
多くの場合、属性が不明な場合、すべての列を別のテーブルに結合することはほとんど意味がありません。これによりNULL
、より単純な設計で s を使用できるようになります。結合のオーバーヘッド、主キーのスペース要件は、現実の世界ではほとんど意味がありません。
これは、カーディナリティ列を追加することで重複行を排除できる方法を思い起こさせますが、理論的には一意のキーを持たないという問題を解決しますが、実際には、たとえば大規模なデータでは不可能な場合があります。純粋主義者は代わりにサロゲート PK をすぐに提案しますが、無意味なサロゲートがリレーション (テーブル) のタプル (行) の一部を形成できるという考えは、リレーショナル理論の観点からは笑いものです。
ヌルマーカーは問題ありません。本当にそうです。
NULL の使用には、いくつかの異論があります。反対意見のいくつかは、データベース理論に基づいています。理論的には、理論と実践の間に違いはありません。実際には、あります。
完全に正規化されたデータベースは、NULL がまったくなくてもうまくいくことは事実です。データ値を除外する必要がある場所は、情報を失うことなく行全体を除外できる場所です。
実際には、この程度までテーブルを分解しても、あまり有用な目的にはなりません。また、データベースで単純な CRUD 操作を実行するために必要なプログラミングは、少なくなるどころか、より退屈でエラーが発生しやすくなります。
NULLS の使用が問題を引き起こす可能性がある場所があります: 基本的に、これらは次の質問を中心に展開します: 欠損データとは実際には何を意味するのでしょうか? NULL が実際に伝えるのは、特定のフィールドに値が格納されていないということだけです。しかし、アプリケーション プログラマーが欠落データから引き出す推論は正しくない場合があり、それが多くの問題を引き起こします。
さまざまな理由で、ある場所からデータが失われる可能性があります。ここにいくつかあります:
データは、このコンテキストでは適用できません。たとえば、独身者の配偶者の名。
データ入力フォームのユーザーがフィールドを空白のままにしましたが、アプリケーションはフィールドへの入力を必要としません。
データは他のデータベースまたはファイルからデータベースにコピーされ、ソースに欠落データがありました。
外部キーでエンコードされたオプションの関係があります。
空の文字列が Oracle データベースに格納されました。
NULLS を回避する場合のガイドラインを次に示します。
通常の予想されるプログラミングの過程で、クエリ作成者は、NULL を有効な値に置き換えるために、ISNULL、NV、COALESCE、または同様のコードを大量に記述する必要があります。保存されているものが「現実」である場合、保存時に置換を行う方が良い場合があります。
NULL を含む行がカウントされたため、カウントがずれている可能性がある場合。多くの場合、count(*) の代わりに count(MyField) を選択するだけで、これを回避できます。
LEFT JOIN や RIGHT JOIN などの外部結合を使い始めるときはいつでも、NULL に慣れ、それに応じてプログラミングする必要があります。内部結合とは異なり、外部結合の背後にある全体的なポイントは、一致するデータが欠落しているときに行を取得することです。欠落しているデータは NULLS として与えられます。
私の結論は、理論を理解せずに却下しないことです。しかし、いつ理論から離れるべきか、またそれに従う方法を学びましょう。
データフィールドにNULLを使用しても問題はありません。キーをnullに設定するときは注意する必要があります。主キーは決してNULLであってはなりません。外部キーはnullにすることができますが、孤立したレコードを作成しないように注意する必要があります。
何かが「存在しない」場合は、空の文字列や他の種類のフラグの代わりにNULLを使用する必要があります。
NULL、トライステート対ブール論理などの問題をすべて書き上げる代わりに、次の簡潔なアドバイスを提供します。
欠落したデータまたは不完全なデータを表す魔法の値を追加するまでは、列に NULL を許可しないでください。
この質問をしているので、 NULL にアプローチする方法には十分注意する必要があります。それには多くの非自明な落とし穴があります。疑わしい場合は、NULL を使用しないでください。
"N/A" または "N/K" または空の文字列を使用する別の方法があります - 別のテーブルです。
たとえば、お客様の電話番号を知っている場合と知らない場合があります。
CREATE TABLE Customer (ID int PRIMARY KEY, Name varchar(100) NOT NULL, Address varchar(200) NOT NULL);
CREATE TABLE CustomerPhone (ID int PRIMARY KEY, Phone varchar(20) NOT NULL, CONSTRAINT FK_CustomerPhone_Customer FOREIGN KEY (ID) REFERENCES Customer (ID));
電話番号がわからない場合は、2 番目のテーブルに行を追加しません。
フィールドを NULL 可能にすることによって生じる複雑さを過小評価しないでください。たとえば、次の where 句は、すべての行に一致するように見えます (ビットは 1 または 0 のみですよね?)
where bitfield in (1,0)
ただし、ビットフィールドが NULLable の場合、一部が失われます。または、次のクエリを実行します。
select * from mytable
where id not in (select id from excludetable)
excludetable に null と 1 が含まれている場合、これは次のように変換されます。
select * from mytable
where id <> NULL and id <> 1
ただし、「id <> NULL」は id の値に対して false であるため、行が返されることはありません。これには、経験豊富なデータベース開発者でさえ驚きます。
ほとんどの人が NULL によって不意を突かれる可能性があることを考えると、私はできる限りそれを避けるようにしています。
Null は必ず使用する必要があります。データの欠如を表す他の正しい方法はありません。たとえば、空の文字列を使用して欠落している住所行を表すのは誤りであり、0 を使用して欠落している年齢データ項目を表すのは誤りです。空の文字列と 0 の両方がデータであるためです。Null は、このようなシナリオを表す最良の方法です。
NULL は非常に多くのことを意味する可能性があるため、これはワームの巨大な缶です。
- 本人は存命のため、死亡日はありません。
- それが何であるか、または存在するかどうかさえわからないため、携帯電話番号はありません。
- その人は社会保障番号を持っていないことがわかっているため、社会保障番号はありません。
これらの一部は正規化によって回避でき、一部はその列に値が存在することで回避でき (「N/A」)、一部は NULL の存在を説明する別の列を持つことで軽減できます。 (「N/K」、「N/A」など)。
それらを見つけるために必要な SQL 構文は非 null 値の構文とは異なり、それらを結合することは困難であり、通常はインデックス エントリに含まれないため、ワームの可能性もあります。
前者の理由により、null が避けられない場合があります。
後者の理由により、それらの数を最小限に抑えるために最善を尽くす必要があります。
とにかく、常に NOT NULL 制約を使用して、値が必要な場所で null を防止してください。
正規形について知っておくべき最善のことは、正規形はガイドであり、ガイドに固執するべきではないということです。アカデミアの世界が現実の世界と衝突するとき、アカデミアの多くの生き残った戦士を見つけることはめったにありません。
この質問に対する答えは、null を使用しても問題ないということです。状況を評価して、テーブルに表示するか、実際の値に対する null 値の比率が高すぎると思われる場合は、データを別の関連するテーブルに折りたたむかを決定してください。
ある友人は、「完璧を善の敵にしないでください」とよく言います。ヴォルテールもそう言ってた気がする 8)
厳密な関係代数によれば、nullは必要ありません。ただし、実際のプロジェクトでは、それらが必要です。
まず、多くの実際のデータは不明であるか適用できないため、nullはその動作を適切に実装します。次に、ビューと外部結合をはるかに実用的にします。
ステップバイステップのデータ取得システムでは、質問をする/データ収集の順序が論理データモデルと一致することはほとんどないため、データベースにヌルが含まれることを避けることができないことがわかります。
または、値をデフォルトにすることもできます (これらのデフォルト値を処理するにはコードが必要です)。たとえば、モデルでは、すべての文字列が null ではなく空であると想定できます。
または、実際のデータベース テーブルに入力する前に、すべてのデータが取得されるまで継続するデータ取得用のステージング データベース テーブルを用意することもできます。これは多くの余分な作業です。
データベースにとって、null は「これには値がありません」と解釈されます。つまり、(興味深いことに) null を許可するブール列は完全に受け入れられ、多くのデータベース スキーマに表示されます。対照的に、コードに「true」、「false」、または「undefined」の値を持つブール値がある場合、コードが遅かれ早かれ thedailywtf に表示される可能性があります :)
はい、フィールドに値がまったくない可能性を考慮する必要がある場合は、列に null を許可することは完全に受け入れられます。潜在的な代替手段(空の文字列、ゼロなど)よりもはるかに優れています
Null は扱いにくい場合がありますが、場合によっては意味があります。
日付値を持つ「PaidDate」列を持つ請求書テーブルがあるとします。請求書が支払われる前に、その列に何を入力しますか (いつ支払われるかを前もって知らないと仮定して)? 有効な日付ではないため、空の文字列にすることはできません。任意の日付 (1900 年 1 月 1 日など) を指定しても意味がありません。その日付は正しくないからです。値がないため、唯一の妥当な値は NULL のようです。
データベースでヌルを扱うにはいくつかの課題がありますが、データベースはそれらをうまく処理します。本当の問題は、データベースからアプリケーション コードに null をロードする場合です。それは私が物事がより困難であることを発見したところです. たとえば、.NET では、厳密に型指定されたデータセット (DB 構造を模倣) の日付は値型であり、null にすることはできません。したがって、回避策を構築する必要があります。
可能な場合は null を避けますが、有効な用途があるため、除外しないでください。
概念データ モデリングと物理データ モデリングを混同していると思います。
CDM では、オブジェクトにオプションのフィールドがある場合、オブジェクトをサブタイプ化し、そのフィールドが null でない場合に備えて新しいオブジェクトを作成する必要があります。それがCDMの理論です
物理的な世界では、現実の世界のためにあらゆる種類の妥協をします。現実の世界では、NULL は問題なく、不可欠です
上記の回答の多くに同意します。また、適切な場合、正規化されたスキーマ設計で NULL を使用できると考えています。特に、ある種の「マジック ナンバー」またはデフォルト値の使用を避けたい場合は、誤解を招く!
ただし、最終的には、特に NULL が「何もない」または「空」、「不明」であると想定される場合に、上記の回答にリストされている仮定の一部を回避するために、(デフォルトではなく) null の使用を十分に検討する必要があると思います。」または「値がまだ入力されていません」。
null は値がないことを意味しますが、0 はそうではありません。
null の方がはるかに明確だと思います。0 と '' は、格納されている値の意図を明確に示していないため、混乱を招きます。
ヌル岩。場合によっては必要ない場合、SQL は IS NULL および IS NOT NULL を特殊なケースの演算子として使用しません。NULL は概念的なユニバーサルのルートであり、それ以外はすべて NOT NULL です。データ値が存在しないが見逃されない可能性がある場合はいつでも、NULL を自由に使用してください。デフォルト値は、それらが常に完全に正しい場合にのみ NULL を補正できます。たとえば、単一ビット フィールド「IsReady」がある場合、このフィールドのデフォルト値が false で NULL が許可されていないことは完全に理にかなっているかもしれませんが、これは暗黙のうちに、私たちが知っていることを主張します。実際にはそのような知識を持っていないかもしれないのに、準備ができていないものは何でも。ワークフローのシナリオでは、準備ができているかどうかを決定する人は、まだ意見を入力する機会がなかっただけである可能性があります。作成されましたが、実際にはデフォルトのみでした。
余談ですが、ミドルネームの例に関して言えば、私の父にはミドルネームがありませんでした。したがって、彼のミドルネームのイニシャルは空白、スペース、またはアスタリスクではなく、NULL になります。例外として、彼のミドルネームのイニシャルは NMI = No Middle でした。イニシャル。それはどれほどばかげていましたか?
その日の私の論争の的となった意見 - データベースの列に NULL を許可するというデフォルトは、おそらくすべての RDBM の世界で広く受け入れられている最悪の設計決定でした。すべてのベンダーがそうしていますが、それは間違っています。特定の特定のよく考えられたインスタンスでは NULL は問題ありませんが、すべての列で NULL を明示的に禁止する必要があるという考えは、過失による null 許容性を本来よりも一般的なものにしています。
Oracle データベースを使用している場合の 1 つの落とし穴。空の文字列を CHAR 型の列に保存すると、Oracle は確認せずに値を強制的に NULL にします。そのため、Oracle の文字列列で NULL 値を回避することは非常に困難です。
NULL 値を使用している場合は、特に文字列値で SQL コマンド COALESCE を使用する方法を学んでください。その後、プログラミング言語に NULL 値が伝播するのを防ぐことができます。たとえば、FirstName、MiddleName、および FamilyName を持っている人が、1 つのフィールドを返したいとします。
SELECT FullName = COALESCE(FirstName + ' ', '') + COALESCE(MiddleName+ ' ', '') + COALESCE(FamilyName, '') FROM Person
COALESCE を使用しない場合、いずれかの列にNULL値が含まれていると、 NULLが返されます。
技術的には、リレーショナル データベースの基礎となるリレーショナル計算では、null は違法です。したがって、純粋に技術的なセマンティック リレーショナル モデルの観点からは、いいえ、問題ありません。
現実の世界では、非正規化とモデルのいくつかの違反は問題ありません。ただし、一般に、ヌルは設計全体をより詳しく調べる必要があることを示しています。
私は常にヌルに非常に警戒しており、可能な限りヌルを正規化しようとしています。しかし、それは時々彼らが最良の選択ではないという意味ではありません. ただし、特定のベースでヌルを使用する方が良いと本当に確信していない限り、私は間違いなく「ヌルなし」の側に傾きます。
私の言葉を皮肉に受け止めないでください。おもちゃのデータベースを扱っていない限り、NULL は避けられず、実際には NULL 値を避けることはできません。
どうすればすべての人にファーストネーム、ミドルネーム、ラストネームを付けることができるかを言うだけです。(ミドルネームとラストネームはオプションです。その場合は NULL が表示されます)、ブログ リストの全員にファックス、会社の電話、オフィスの電話を設定する方法。
NULLS は問題なく、検索時に適切に処理する必要があります。SQL Server 2008 には、NULL にも使用されるスペースを回避できるスパース列の概念があります。
NULL をゼロやその他の値と混同しないでください。人々はそれが正しいと言います。
ありがとうナヴィーン
技術的には NULL はフィールド値として問題ありませんが、非常に頻繁に嫌われます。データベースへのデータの書き込み方法によっては、NULL ではなく空の文字列値がフィールドに表示される可能性があります (そして一般的です)。したがって、このフィールドを WHERE 句の一部として持つクエリは、不要なキーストロークである両方のシナリオを処理する必要があります。
個人的には、フィールドを別のテーブルへの外部キーとして使用している場合にのみ、このレコードが他のテーブルの何にもリンクしていないことを象徴するために、null を使用する必要があると思います。それ以外では、アプリケーション ロジックをプログラミングするときに null 値が実際に非常に厄介であることがわかりました。ほとんどのプログラミング言語では、多くのデータ型に対してデータベース null を直接表現することはできないため、これらの null 値の意味を処理するために多くのアプリケーション コードを作成することになります。DB が null 整数に遭遇し、たとえば値 1 を追加しようとすると (別名 null + 1)、ロジックが定義されているため、データベースは null を返します。ただし、プログラミング言語が null と 1 を追加しようとすると、通常は例外がスローされます。したがって、コードは、値が null の場合に何をすべきかのチェックで散らかってしまいます。
問題は、NULL の値を解釈して意味するものに帰着すると思います。はい、NULL 値には多くの解釈がありますが、ここに掲載されているものの中には使用しないでください。NULL の真の意味は、アプリケーションのコンテキストによって決定され、複数のことを意味することはありません。たとえば、生年月日フィールドの NULL は、その人がまだ生きていることを示すという提案がありました。これは危険です。
簡単にするために、NULL を定義し、それに固執します。「現時点では、このフィールドの値は不明です」という意味で使用します。それはそれを意味し、それだけです。他の意味を持たせる必要がある場合は、データ モデルを再検討する必要があります。
属性のコンテキスト内で null が有効な場合は、許可する必要があるようです。
しかし、null とはどういう意味ですか? それがこすりです。それは「値なし」ですが、そこに値がない可能性があるさまざまな理由が多数あります。この場合、「null」はそれが何を意味するかについての手がかりを与えません。(まだ設定されていない、このインスタンスには適用されない、このタイプには適用されない、不明、不明、見つからない、エラー、プログラムのバグ、...)
これは、オブジェクト参照が null であることが多い Java では非常に一般的です。
null 参照も悪いという考え方があります。同じ問題: null とはどういう意味ですか?
IIRC、Java には「null」と「uninitialized」の両方があります (ただし、後者の構文はありません)。したがって、ゴスリングは、あらゆる種類の「値なし」に「null」を使用することの愚かさに気付きました。しかし、なぜ2 つだけで終わるのでしょうか。
それはすべて、正規化と使いやすさ、およびパフォーマンスの問題に帰着します。
完全な正規化ルールに固執する場合は、次のようなものを書くことになります。
c.id, c.lastname,....... を選択します。顧客 c から c.id = cpn.customerid で customerphonenumber cpn に参加します。 c.id = ca.customerid で customeraddress ca に参加します。 id = cpn2.customerid などなど
nullで絶対に問題ありません。
関連する質問:データベースにデータ整合性ルールを適用するにはどうすればよいですか?
最初は、nullalbe フィールドがほぼゼロの小さなテーブルを多数用意することから始めました。次に、LINQ to SQL の IsDiscriminator プロパティと、LINQ to SQL がサポートするのは単一テーブルの継承のみであることを学びました。したがって、多くの nullalbe フィールドを持つ単一のテーブルとして再設計しました。
30 年の経験を持つアナリスト/プログラマーとして、NULL は取り戻されて悲惨な状況から解放されるべきだとだけ言いたい。
-1、01/01/0001/12/31/9999 および ? これらの厄介なNULLに対処するために必要なコードを歪めることなく、すべて同様に十分です。