web-dev-qa-db-ja.com

Oracleでnull許容値を使用しない理由は?

私たちの会社は、共同プロジェクトのために別のソフトウェア会社とインターフェースをとっており、特定の値を表示しない場合は-5000(任意のセンチネル値)を渡す必要があると言われました。その理由は、彼らの(現在は以前の)Oracle開発者の推奨により、Oracleデータベースの数値列がnull値をサポートしないためです。この会社はまた、コードの大部分をVB6で記述しています(ゆっくりとVB.NETに移行します。これは別の日の別のトピックです...)。純粋な好奇心から、この勧告に正当な理由はありますか?私の側には何も思いつきません。

---編集

すべてのフィードバックに感謝します。 CodeProject.com( link )にも同じ質問を投げかけ、非常によく似たフィードバックを受けました。この慣行を正当化し始める可能性があるのは、外部キーに関連する唯一の場合であり、システムのどこにも外部キーを使用していないと私は述べることができます。この決定を下した開発者(私は以前その会社で働いていました)は私よりもはるかに多くの経験を持っているので、私はあざけりが起こる前にこれの正当な理由がないことを確認したかったのです。

12

現実的には、要件は狂っています。すべての素晴らしいクレイジーなアイデアと同様に、それはおそらく、根本的な根拠を理解していない人々が文脈から遠く離れた潜在的な合理性のナゲットに基づいているでしょう。

NULL値が許可されないようにデータベーススキーマを設計することは合理的です。ただし、これを行うと、正規化のレベルにコミットすることになります。この場合、必須ではないすべての要素が、親への適切な外部キー参照を含む個別のテーブルに分割されます。実際に行われることはあまりありませんが、行うのが理にかなっている場合は、メリットがある場合があります。

NULL値が許可されないようにデータベーススキーマを設計する場合、何かが不明であることを示すために魔法の値を要求することはできません。これにより、NULL値を許可することで発生するすべての問題が発生し、さらに、場所全体で繰り返される魔法の値をチェックするためのコードが追加されます。データベースの設計に関係なく魔法の値を渡す必要があるAPIを開発しても意味がありません。魔法の値のチェックでコードを破壊する場合は、その狂気を他のシステムに伝播させてはいけません。 。

17
Justin Cave

有効な理由はありません NULLの代わりにマジック値を使用します。これは、この混乱を作成している誰かの思考プロセスかもしれません。彼らはこのようなものを書きます:

 SELECT c1, c2 FROM t1 WHERE c3 < 30;

これが期待した結果を返さない場合、NULLが含まれていないため、次のように記述する必要があります。

SELECT c1, c2 FROM t1 WHERE c3 < 30 OR c3 IS NULL;

彼らはこれを書いたくないし、将来これを書くことを忘れたくないので、すべてNULLS -5000にするという解決策を考え出します。魔法のように、元のクエリは変更なしでNULLを処理します。彼らが気付いていないのは、これらの値を除外したい人がこれを書かなければならないということです:

SELECT c1, c2 FROM t1 WHERE c3 < 30 AND c3 <> -5000;

または、これらの値が必要で、より高い範囲を検索している場合:

SELECT c1, c2 FROM t1 WHERE c3 > 40 OR c3 = -5000;

また、次のことが意味をなさなくなることに気付かない場合もあります。

SELECT c1, c2 FROM t1 WHERE c3 IS NULL;

代わりに、人は魔法の価値を覚えなければなりません。使用される各データ型では、より多くのマジック値を覚える必要があります。 1900/1/1、「Z」、-5000。さらに、マジック値がデータ内にある場合、代替のマジック値も覚えておく必要があります。

したがって、特定のケースでは、ディスクスペース、インデックスサイズ、クエリの解析、一貫性などは言うまでもなく、他のケースを犠牲にしてコードが単純になります。

15
Leigh Riffel

それは全くの狂気であり、それを正当化する理由はありません。 NULLは、値が存在しないことを表し、-5000のような実際の値を使用するために作成されました。

通常、私はこの短い答えを書きませんが、質問はdba.seで最も目に見えるものの1つに値するはずです。

8
Philᵀᴹ

私はこれを少しポジティブにしようとし、nullの代わりに任意の値を使用する必要性を正当化することを考えました、そしてを除いて、(少なくとも私にとって)これには正当な理由がないようですパフォーマンスとクエリを改善および簡略化するために閉じたデータマイニングデータセット内で、数値がデータを歪める可能性のある値でない場合のみ。これも慎重に検討する必要があります。すべての現実世界の状況で、nullに値を与えることは良い習慣ではありません。これは実際には真実ではないため、NOT NULL列の定義を友達から敵に変えます。

アプリケーションが一部(またはすべて)の列にNULL値を受け入れないようにする必要があると言うのは非常に異なります。これは賢明で優れた方法であり、nullを許可しないことには十分に文書化された利点があります(たとえば、キーとインデックス、統計計算など)。ただし、nullの「sit in the place」に値を割り当てることはまったく同じではありません。それはあなた自身の背中のためのロッドです、あなたは最初に決して決して使われないであろう値を選択しなければならないので、あなたはnullと同じようにこの値を除外し、計算と要約でそれを使わないことを覚えて、外部データフィードからそれを削除してください。 。これは、実際の値を表すためにnullを使用することと少なくとも同じぐらい悪いことです。

Nullが引き起こすほとんどの問題は、いったん理解されれば、対処できます(より良い正規化、関数ベースまたはビットマップインデックス、または単純なWHERE x IS NOT NULL)で対処できます)。またはAmazonで毎月のパフォーマンスミーティングで一部のDBAは、巨大なデータセットに対するクエリを少し高速化するためのこの素晴らしい計画の概要を説明しています。「nullを-5000などの任意の値に置き換えて、値を公開しています。 .. "。または、不要なnullを除外するための優れたアプリケーション設計と、与えられた実際のデータに基づいたクエリ最適化の間で時間を費やしていると思いますか?少し楽観的ですが、それらが発生するときはいつでも、「より良いAPIのためにnullを-5000(または何でも)で置き換えること」は議題ではないことを保証できます。

私にとっては、欠落しているデータ(年齢、価格、または地域コードなどが必要です)を受け入れないことを言うのは問題ありません。この列については、場合によっては入力されるデフォルト値があると言っても問題ありません他には何も入れません。 nullを意味するように値を脇に置いておくことはできません。例としてミドルネームフィールドについて考えてください。両親は怠惰すぎてすべてのボックスを埋めることができないため、これらは存在しない場合があります。検索を改善するために、データに「なし」、「欠落」、または「不明」を追加しますか?いいえ、名前をこれらの値に変更する奇妙な人々がいる可能性があるため、データを印刷するときに、含める必要があるかどうかわかりません。これは単純ですが、広範囲に及ぶ例です。私たちはNULLについて知っており、それに対処するための予測可能な組み込み関数を持っています。これをこれ以上コーディングすることはできません。

応答がない(またはNULL)が入力要求に対する有効な応答でない場合は、アプリケーションまたはデータベースで許可しないでください。応答が適切な場合は、アプリケーションとデータベースの両方で許可して対処する必要があります。有効な応答として。それが一連​​の有効な応答の一部である場合、データベースはそれを格納するように設計する必要があります。結局のところ、数値フィールドは非常に退屈なので、数値をBLOBに格納し、野生動物の写真を使用して各数値を表すことができます。また、Bという文字が気に入らないとは判断しません。また、残酷なセサミストリートの悪夢のように、データ内の#に置き換えます。 Bが応答でない場合は、ユーザーに「ねえ、ここにBを置くことはできません」と伝えます。では、なぜnullを別の方法で扱うのでしょうか。

したがって、アプリケーションレベルでは不要なnullを回避し、データベースでそれらを処理します。nullを受け入れる場合は、それ以外の場合は受け入れます。キリン+キリン=カバ無意味なデータラングリングによって問題が発生します。

5
user3629